1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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  * https://systemd.io/PREDICTABLE_INTERFACE_NAMES
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 <stdarg.h>
19 #include <unistd.h>
20 #include <linux/if.h>
21 #include <linux/if_arp.h>
22 #include <linux/netdevice.h>
23 #include <linux/pci_regs.h>
24 
25 #include "alloc-util.h"
26 #include "chase-symlinks.h"
27 #include "device-util.h"
28 #include "dirent-util.h"
29 #include "fd-util.h"
30 #include "fileio.h"
31 #include "netif-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 #include "udev-netlink.h"
40 
41 #define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
42 #define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
43 
44 typedef enum NetNameType {
45         NET_UNDEF,
46         NET_PCI,
47         NET_USB,
48         NET_BCMA,
49         NET_VIRTIO,
50         NET_CCW,
51         NET_VIO,
52         NET_XENVIF,
53         NET_PLATFORM,
54         NET_NETDEVSIM,
55 } NetNameType;
56 
57 typedef struct NetNames {
58         NetNameType type;
59 
60         sd_device *pcidev;
61         char pci_slot[ALTIFNAMSIZ];
62         char pci_path[ALTIFNAMSIZ];
63         char pci_onboard[ALTIFNAMSIZ];
64         const char *pci_onboard_label;
65 
66         char usb_ports[ALTIFNAMSIZ];
67         char bcma_core[ALTIFNAMSIZ];
68         char ccw_busid[ALTIFNAMSIZ];
69         char vio_slot[ALTIFNAMSIZ];
70         char xen_slot[ALTIFNAMSIZ];
71         char platform_path[ALTIFNAMSIZ];
72         char netdevsim_path[ALTIFNAMSIZ];
73 } NetNames;
74 
75 /* skip intermediate virtio devices */
skip_virtio(sd_device * dev)76 static sd_device *skip_virtio(sd_device *dev) {
77         /* there can only ever be one virtio bus per parent device, so we can
78          * safely ignore any virtio buses. see
79          * http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html */
80         while (dev) {
81                 const char *subsystem;
82 
83                 if (sd_device_get_subsystem(dev, &subsystem) < 0)
84                         break;
85 
86                 if (!streq(subsystem, "virtio"))
87                         break;
88 
89                 if (sd_device_get_parent(dev, &dev) < 0)
90                         return NULL;
91         }
92 
93         return dev;
94 }
95 
get_virtfn_info(sd_device * pcidev,sd_device ** ret_physfn_pcidev,char ** ret_suffix)96 static int get_virtfn_info(sd_device *pcidev, sd_device **ret_physfn_pcidev, char **ret_suffix) {
97         _cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
98         const char *physfn_syspath, *syspath;
99         _cleanup_closedir_ DIR *dir = NULL;
100         int r;
101 
102         assert(pcidev);
103         assert(ret_physfn_pcidev);
104         assert(ret_suffix);
105 
106         r = sd_device_get_syspath(pcidev, &syspath);
107         if (r < 0)
108                 return r;
109 
110         /* Get physical function's pci device. */
111         physfn_syspath = strjoina(syspath, "/physfn");
112         r = sd_device_new_from_syspath(&physfn_pcidev, physfn_syspath);
113         if (r < 0)
114                 return r;
115 
116         r = sd_device_get_syspath(physfn_pcidev, &physfn_syspath);
117         if (r < 0)
118                 return r;
119 
120         /* Find the virtual function number by finding the right virtfn link. */
121         dir = opendir(physfn_syspath);
122         if (!dir)
123                 return -errno;
124 
125         FOREACH_DIRENT_ALL(de, dir, break) {
126                 _cleanup_free_ char *virtfn_link_file = NULL, *virtfn_pci_syspath = NULL;
127                 const char *n;
128 
129                 n = startswith(de->d_name, "virtfn");
130                 if (!n)
131                         continue;
132 
133                 virtfn_link_file = path_join(physfn_syspath, de->d_name);
134                 if (!virtfn_link_file)
135                         return -ENOMEM;
136 
137                 if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0)
138                         continue;
139 
140                 if (streq(syspath, virtfn_pci_syspath)) {
141                         char *suffix;
142 
143                         suffix = strjoin("v", n);
144                         if (!suffix)
145                                 return -ENOMEM;
146 
147                         *ret_physfn_pcidev = TAKE_PTR(physfn_pcidev);
148                         *ret_suffix = suffix;
149                         return 0;
150                 }
151         }
152 
153         return -ENOENT;
154 }
155 
is_valid_onboard_index(unsigned long idx)156 static bool is_valid_onboard_index(unsigned long idx) {
157         /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
158          * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
159          * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
160          * interface a system might have. Ideally the kernel would already filter this crap for us, but it
161          * doesn't currently. The initial cut-off value (2^14-1) was too conservative for s390 PCI which
162          * allows for index values up 2^16-1 which is now enabled with the NAMING_16BIT_INDEX naming flag. */
163         return idx <= (naming_scheme_has(NAMING_16BIT_INDEX) ? ONBOARD_16BIT_INDEX_MAX : ONBOARD_14BIT_INDEX_MAX);
164 }
165 
166 /* retrieve on-board index number and label from firmware */
dev_pci_onboard(sd_device * dev,const LinkInfo * info,NetNames * names)167 static int dev_pci_onboard(sd_device *dev, const LinkInfo *info, NetNames *names) {
168         unsigned long idx, dev_port = 0;
169         const char *attr;
170         size_t l;
171         char *s;
172         int r;
173 
174         assert(dev);
175         assert(info);
176         assert(names);
177 
178         /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
179         if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) >= 0)
180                 log_device_debug(names->pcidev, "acpi_index=%s", attr);
181         else {
182                 /* SMBIOS type 41 — Onboard Devices Extended Information */
183                 r = sd_device_get_sysattr_value(names->pcidev, "index", &attr);
184                 if (r < 0)
185                         return r;
186                 log_device_debug(names->pcidev, "index=%s", attr);
187         }
188 
189         r = safe_atolu(attr, &idx);
190         if (r < 0)
191                 return log_device_debug_errno(names->pcidev, r,
192                                               "Failed to parse onboard index \"%s\": %m", attr);
193         if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
194                 return log_device_debug_errno(names->pcidev, SYNTHETIC_ERRNO(EINVAL),
195                                               "Naming scheme does not allow onboard index==0.");
196         if (!is_valid_onboard_index(idx))
197                 return log_device_debug_errno(names->pcidev, SYNTHETIC_ERRNO(ENOENT),
198                                               "Not a valid onboard index: %lu", idx);
199 
200         /* kernel provided port index for multiple ports on a single PCI function */
201         if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
202                 r = safe_atolu_full(attr, 10, &dev_port);
203                 if (r < 0)
204                         log_device_debug_errno(dev, r, "Failed to parse dev_port, ignoring: %m");
205                 log_device_debug(dev, "dev_port=%lu", dev_port);
206         }
207 
208         s = names->pci_onboard;
209         l = sizeof(names->pci_onboard);
210         l = strpcpyf(&s, l, "o%lu", idx);
211         if (!isempty(info->phys_port_name))
212                 /* kernel provided front panel port name for multiple port PCI device */
213                 l = strpcpyf(&s, l, "n%s", info->phys_port_name);
214         else if (dev_port > 0)
215                 l = strpcpyf(&s, l, "d%lu", dev_port);
216         if (l == 0)
217                 names->pci_onboard[0] = '\0';
218         log_device_debug(dev, "Onboard index identifier: index=%lu phys_port=%s dev_port=%lu → %s",
219                          idx, strempty(info->phys_port_name), dev_port,
220                          empty_to_na(names->pci_onboard));
221 
222         if (sd_device_get_sysattr_value(names->pcidev, "label", &names->pci_onboard_label) >= 0)
223                 log_device_debug(dev, "Onboard label from PCI device: %s", names->pci_onboard_label);
224         else
225                 names->pci_onboard_label = NULL;
226 
227         return 0;
228 }
229 
230 /* read the 256 bytes PCI configuration space to check the multi-function bit */
is_pci_multifunction(sd_device * dev)231 static bool is_pci_multifunction(sd_device *dev) {
232         _cleanup_close_ int fd = -1;
233         const char *filename, *syspath;
234         uint8_t config[64];
235 
236         if (sd_device_get_syspath(dev, &syspath) < 0)
237                 return false;
238 
239         filename = strjoina(syspath, "/config");
240         fd = open(filename, O_RDONLY | O_CLOEXEC);
241         if (fd < 0)
242                 return false;
243         if (read(fd, &config, sizeof(config)) != sizeof(config))
244                 return false;
245 
246         /* bit 0-6 header type, bit 7 multi/single function device */
247         return config[PCI_HEADER_TYPE] & 0x80;
248 }
249 
is_pci_ari_enabled(sd_device * dev)250 static bool is_pci_ari_enabled(sd_device *dev) {
251         const char *a;
252 
253         if (sd_device_get_sysattr_value(dev, "ari_enabled", &a) < 0)
254                 return false;
255 
256         return streq(a, "1");
257 }
258 
is_pci_bridge(sd_device * dev)259 static bool is_pci_bridge(sd_device *dev) {
260         const char *v, *p;
261 
262         if (sd_device_get_sysattr_value(dev, "modalias", &v) < 0)
263                 return false;
264 
265         if (!startswith(v, "pci:"))
266                 return false;
267 
268         p = strrchr(v, 's');
269         if (!p)
270                 return false;
271         if (p[1] != 'c')
272                 return false;
273 
274         /* PCI device subclass 04 corresponds to PCI bridge */
275         bool b = strneq(p + 2, "04", 2);
276         if (b)
277                 log_device_debug(dev, "Device is a PCI bridge.");
278         return b;
279 }
280 
parse_hotplug_slot_from_function_id(sd_device * dev,const char * slots,uint32_t * ret)281 static int parse_hotplug_slot_from_function_id(sd_device *dev, const char *slots, uint32_t *ret) {
282         uint64_t function_id;
283         char path[PATH_MAX];
284         const char *attr;
285         int r;
286 
287         /* The <sysname>/function_id attribute is unique to the s390 PCI driver. If present, we know
288          * that the slot's directory name for this device is /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is
289          * the fixed length 8 hexadecimal character string representation of function_id. Therefore we
290          * can short cut here and just check for the existence of the slot directory. As this directory
291          * has to exist, we're emitting a debug message for the unlikely case it's not found. Note that
292          * the domain part doesn't belong to the slot name here because there's a 1-to-1 relationship
293          * between PCI function and its hotplug slot. */
294 
295         assert(dev);
296         assert(slots);
297         assert(ret);
298 
299         if (!naming_scheme_has(NAMING_SLOT_FUNCTION_ID))
300                 return 0;
301 
302         if (sd_device_get_sysattr_value(dev, "function_id", &attr) < 0)
303                 return 0;
304 
305         r = safe_atou64(attr, &function_id);
306         if (r < 0)
307                 return log_device_debug_errno(dev, r, "Failed to parse function_id, ignoring: %s", attr);
308 
309         if (function_id <= 0 || function_id > UINT32_MAX)
310                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
311                                               "Invalid function id (0x%"PRIx64"), ignoring.",
312                                               function_id);
313 
314         if (!snprintf_ok(path, sizeof path, "%s/%08"PRIx64, slots, function_id))
315                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENAMETOOLONG),
316                                               "PCI slot path is too long, ignoring.");
317 
318         if (access(path, F_OK) < 0)
319                 return log_device_debug_errno(dev, errno, "Cannot access %s, ignoring: %m", path);
320 
321         *ret = (uint32_t) function_id;
322         return 1;
323 }
324 
dev_pci_slot(sd_device * dev,const LinkInfo * info,NetNames * names)325 static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
326         const char *sysname, *attr, *syspath;
327         _cleanup_(sd_device_unrefp) sd_device *pci = NULL;
328         _cleanup_closedir_ DIR *dir = NULL;
329         unsigned domain, bus, slot, func;
330         sd_device *hotplug_slot_dev;
331         unsigned long dev_port = 0;
332         uint32_t hotplug_slot = 0;
333         char slots[PATH_MAX], *s;
334         size_t l;
335         int r;
336 
337         assert(dev);
338         assert(info);
339         assert(names);
340 
341         r = sd_device_get_sysname(names->pcidev, &sysname);
342         if (r < 0)
343                 return log_device_debug_errno(names->pcidev, r, "Failed to get sysname: %m");
344 
345         r = sscanf(sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func);
346         log_device_debug(dev, "Parsing slot information from PCI device sysname \"%s\": %s",
347                          sysname, r == 4 ? "success" : "failure");
348         if (r != 4)
349                 return -ENOENT;
350 
351         if (naming_scheme_has(NAMING_NPAR_ARI) &&
352             is_pci_ari_enabled(names->pcidev))
353                 /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
354                  * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
355                  * where the slot makes up the upper 5 bits. */
356                 func += slot * 8;
357 
358         /* kernel provided port index for multiple ports on a single PCI function */
359         if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
360                 log_device_debug(dev, "dev_port=%s", attr);
361 
362                 r = safe_atolu_full(attr, 10, &dev_port);
363                 if (r < 0)
364                         log_device_debug_errno(dev, r, "Failed to parse attribute dev_port, ignoring: %m");
365 
366                 /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
367                  * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
368                  * which thus stays initialized as 0. */
369                 if (dev_port == 0 &&
370                     info->iftype == ARPHRD_INFINIBAND &&
371                     sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0) {
372                         log_device_debug(dev, "dev_id=%s", attr);
373 
374                         r = safe_atolu_full(attr, 10, &dev_port);
375                         if (r < 0)
376                                 log_device_debug_errno(dev, r, "Failed to parse attribute dev_id, ignoring: %m");
377                 }
378         }
379 
380         /* compose a name based on the raw kernel's PCI bus, slot numbers */
381         s = names->pci_path;
382         l = sizeof(names->pci_path);
383         if (domain > 0)
384                 l = strpcpyf(&s, l, "P%u", domain);
385         l = strpcpyf(&s, l, "p%us%u", bus, slot);
386         if (func > 0 || is_pci_multifunction(names->pcidev))
387                 l = strpcpyf(&s, l, "f%u", func);
388         if (!isempty(info->phys_port_name))
389                 /* kernel provided front panel port name for multi-port PCI device */
390                 l = strpcpyf(&s, l, "n%s", info->phys_port_name);
391         else if (dev_port > 0)
392                 l = strpcpyf(&s, l, "d%lu", dev_port);
393         if (l == 0)
394                 names->pci_path[0] = '\0';
395 
396         log_device_debug(dev, "PCI path identifier: domain=%u bus=%u slot=%u func=%u phys_port=%s dev_port=%lu → %s",
397                          domain, bus, slot, func, strempty(info->phys_port_name), dev_port,
398                          empty_to_na(names->pci_path));
399 
400         /* ACPI _SUN — slot user number */
401         r = sd_device_new_from_subsystem_sysname(&pci, "subsystem", "pci");
402         if (r < 0)
403                 return log_debug_errno(r, "sd_device_new_from_subsystem_sysname() failed: %m");
404 
405         r = sd_device_get_syspath(pci, &syspath);
406         if (r < 0)
407                 return log_device_debug_errno(pci, r, "sd_device_get_syspath() failed: %m");
408 
409         if (!snprintf_ok(slots, sizeof slots, "%s/slots", syspath))
410                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENAMETOOLONG),
411                                               "Cannot access %s/slots: %m", syspath);
412 
413         dir = opendir(slots);
414         if (!dir)
415                 return log_device_debug_errno(dev, errno, "Cannot access %s: %m", slots);
416 
417         hotplug_slot_dev = names->pcidev;
418         while (hotplug_slot_dev) {
419                 r = parse_hotplug_slot_from_function_id(hotplug_slot_dev, slots, &hotplug_slot);
420                 if (r < 0)
421                         return 0;
422                 if (r > 0) {
423                         domain = 0; /* See comments in parse_hotplug_slot_from_function_id(). */
424                         break;
425                 }
426 
427                 r = sd_device_get_sysname(hotplug_slot_dev, &sysname);
428                 if (r < 0)
429                         return log_device_debug_errno(hotplug_slot_dev, r, "Failed to get sysname: %m");
430 
431                 FOREACH_DIRENT_ALL(de, dir, break) {
432                         _cleanup_free_ char *address = NULL;
433                         char str[PATH_MAX];
434                         uint32_t i;
435 
436                         if (dot_or_dot_dot(de->d_name))
437                                 continue;
438 
439                         r = safe_atou32(de->d_name, &i);
440                         if (r < 0 || i <= 0)
441                                 continue;
442 
443                         /* match slot address with device by stripping the function */
444                         if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, de->d_name) &&
445                             read_one_line_file(str, &address) >= 0 &&
446                             startswith(sysname, address)) {
447                                 hotplug_slot = i;
448 
449                                 /* We found the match between PCI device and slot. However, we won't use the
450                                  * slot index if the device is a PCI bridge, because it can have other child
451                                  * devices that will try to claim the same index and that would create name
452                                  * collision. */
453                                 if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev)) {
454                                         if (naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT) && !is_pci_multifunction(names->pcidev)) {
455                                                 log_device_debug(dev, "Not using slot information because the PCI device associated with the hotplug slot is a bridge and the PCI device has single function.");
456                                                 return 0;
457                                         }
458 
459                                         if (!naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT)) {
460                                                 log_device_debug(dev, "Not using slot information because the PCI device is a bridge.");
461                                                 return 0;
462                                         }
463                                 }
464 
465                                 break;
466                         }
467                 }
468                 if (hotplug_slot > 0)
469                         break;
470                 if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0)
471                         break;
472                 rewinddir(dir);
473         }
474 
475         if (hotplug_slot > 0) {
476                 s = names->pci_slot;
477                 l = sizeof(names->pci_slot);
478                 if (domain > 0)
479                         l = strpcpyf(&s, l, "P%u", domain);
480                 l = strpcpyf(&s, l, "s%"PRIu32, hotplug_slot);
481                 if (func > 0 || is_pci_multifunction(names->pcidev))
482                         l = strpcpyf(&s, l, "f%u", func);
483                 if (!isempty(info->phys_port_name))
484                         l = strpcpyf(&s, l, "n%s", info->phys_port_name);
485                 else if (dev_port > 0)
486                         l = strpcpyf(&s, l, "d%lu", dev_port);
487                 if (l == 0)
488                         names->pci_slot[0] = '\0';
489 
490                 log_device_debug(dev, "Slot identifier: domain=%u slot=%"PRIu32" func=%u phys_port=%s dev_port=%lu → %s",
491                                  domain, hotplug_slot, func, strempty(info->phys_port_name), dev_port,
492                                  empty_to_na(names->pci_slot));
493         }
494 
495         return 0;
496 }
497 
names_vio(sd_device * dev,NetNames * names)498 static int names_vio(sd_device *dev, NetNames *names) {
499         sd_device *parent;
500         unsigned busid, slotid, ethid;
501         const char *syspath, *subsystem;
502         int r;
503 
504         /* check if our direct parent is a VIO device with no other bus in-between */
505         r = sd_device_get_parent(dev, &parent);
506         if (r < 0)
507                 return log_device_debug_errno(dev, r, "sd_device_get_parent() failed: %m");
508 
509         r = sd_device_get_subsystem(parent, &subsystem);
510         if (r < 0)
511                 return log_device_debug_errno(parent, r, "sd_device_get_subsystem() failed: %m");
512         if (!streq("vio", subsystem))
513                 return -ENOENT;
514         log_device_debug(dev, "Parent device is in the vio subsystem.");
515 
516         /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id
517          * selected in the HMC), thus this provides a reliable naming (e.g.
518          * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as
519          * there should only ever be one bus, and then remove leading zeros. */
520         r = sd_device_get_syspath(dev, &syspath);
521         if (r < 0)
522                 return log_device_debug_errno(dev, r, "sd_device_get_syspath() failed: %m");
523 
524         r = sscanf(syspath, "/sys/devices/vio/%4x%4x/net/eth%u", &busid, &slotid, &ethid);
525         log_device_debug(dev, "Parsing vio slot information from syspath \"%s\": %s",
526                          syspath, r == 3 ? "success" : "failure");
527         if (r != 3)
528                 return -EINVAL;
529 
530         xsprintf(names->vio_slot, "v%u", slotid);
531         names->type = NET_VIO;
532         log_device_debug(dev, "Vio slot identifier: slotid=%u → %s", slotid, names->vio_slot);
533         return 0;
534 }
535 
536 #define PLATFORM_TEST "/sys/devices/platform/vvvvPPPP"
537 #define PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
538 #define PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
539 
names_platform(sd_device * dev,NetNames * names,bool test)540 static int names_platform(sd_device *dev, NetNames *names, bool test) {
541         sd_device *parent;
542         char vendor[5];
543         unsigned model, instance, ethid;
544         const char *syspath, *pattern, *validchars, *subsystem;
545         int r;
546 
547         /* check if our direct parent is a platform device with no other bus in-between */
548         r = sd_device_get_parent(dev, &parent);
549         if (r < 0)
550                 return log_device_debug_errno(dev, r, "sd_device_get_parent() failed: %m");
551 
552         r = sd_device_get_subsystem(parent, &subsystem);
553         if (r < 0)
554                 return log_device_debug_errno(parent, r, "sd_device_get_subsystem() failed: %m");
555 
556         if (!streq("platform", subsystem))
557                  return -ENOENT;
558         log_device_debug(dev, "Parent device is in the platform subsystem.");
559 
560         r = sd_device_get_syspath(dev, &syspath);
561         if (r < 0)
562                 return log_device_debug_errno(dev, r, "sd_device_get_syspath() failed: %m");
563 
564         /* syspath is too short, to have a valid ACPI instance */
565         if (strlen(syspath) < STRLEN(PLATFORM_TEST) + 1)
566                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
567                                               "Syspath \"%s\" is too short for a valid ACPI instance.",
568                                               syspath);
569 
570         /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */
571         if (syspath[STRLEN(PLATFORM_TEST)] == ':') {
572                 pattern = PLATFORM_PATTERN4;
573                 validchars = UPPERCASE_LETTERS DIGITS;
574         } else {
575                 pattern = PLATFORM_PATTERN3;
576                 validchars = UPPERCASE_LETTERS;
577         }
578 
579         /* Platform devices are named after ACPI table match, and instance id
580          * eg. "/sys/devices/platform/HISI00C2:00");
581          * The Vendor (3 or 4 char), followed by hexadecimal model number : instance id. */
582 
583         DISABLE_WARNING_FORMAT_NONLITERAL;
584         r = sscanf(syspath, pattern, vendor, &model, &instance, &ethid);
585         REENABLE_WARNING;
586         log_device_debug(dev, "Parsing platform device information from syspath \"%s\": %s",
587                          syspath, r == 4 ? "success" : "failure");
588         if (r != 4)
589                 return -EINVAL;
590 
591         if (!in_charset(vendor, validchars))
592                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENOENT),
593                                               "Platform vendor contains invalid characters: %s", vendor);
594 
595         ascii_strlower(vendor);
596 
597         xsprintf(names->platform_path, "a%s%xi%u", vendor, model, instance);
598         names->type = NET_PLATFORM;
599         log_device_debug(dev, "Platform identifier: vendor=%s model=%u instance=%u → %s",
600                          vendor, model, instance, names->platform_path);
601         return 0;
602 }
603 
names_pci(sd_device * dev,const LinkInfo * info,NetNames * names)604 static int names_pci(sd_device *dev, const LinkInfo *info, NetNames *names) {
605         _cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
606         _cleanup_free_ char *virtfn_suffix = NULL;
607         sd_device *parent;
608         const char *subsystem;
609         int r;
610 
611         assert(dev);
612         assert(info);
613         assert(names);
614 
615         r = sd_device_get_parent(dev, &parent);
616         if (r < 0)
617                 return r;
618         /* skip virtio subsystem if present */
619         parent = skip_virtio(parent);
620 
621         if (!parent)
622                 return -ENOENT;
623 
624         /* check if our direct parent is a PCI device with no other bus in-between */
625         if (sd_device_get_subsystem(parent, &subsystem) >= 0 &&
626             streq("pci", subsystem)) {
627                 names->type = NET_PCI;
628                 names->pcidev = parent;
629         } else {
630                 r = sd_device_get_parent_with_subsystem_devtype(dev, "pci", NULL, &names->pcidev);
631                 if (r < 0)
632                         return r;
633         }
634 
635         if (naming_scheme_has(NAMING_SR_IOV_V) &&
636             get_virtfn_info(names->pcidev, &physfn_pcidev, &virtfn_suffix) >= 0) {
637                 NetNames vf_names = {};
638 
639                 /* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
640                 vf_names.pcidev = physfn_pcidev;
641                 dev_pci_onboard(dev, info, &vf_names);
642                 dev_pci_slot(dev, info, &vf_names);
643 
644                 if (vf_names.pci_onboard[0])
645                         if (strlen(vf_names.pci_onboard) + strlen(virtfn_suffix) < sizeof(names->pci_onboard))
646                                 strscpyl(names->pci_onboard, sizeof(names->pci_onboard),
647                                          vf_names.pci_onboard, virtfn_suffix, NULL);
648                 if (vf_names.pci_slot[0])
649                         if (strlen(vf_names.pci_slot) + strlen(virtfn_suffix) < sizeof(names->pci_slot))
650                                 strscpyl(names->pci_slot, sizeof(names->pci_slot),
651                                          vf_names.pci_slot, virtfn_suffix, NULL);
652                 if (vf_names.pci_path[0])
653                         if (strlen(vf_names.pci_path) + strlen(virtfn_suffix) < sizeof(names->pci_path))
654                                 strscpyl(names->pci_path, sizeof(names->pci_path),
655                                          vf_names.pci_path, virtfn_suffix, NULL);
656         } else {
657                 dev_pci_onboard(dev, info, names);
658                 dev_pci_slot(dev, info, names);
659         }
660 
661         return 0;
662 }
663 
names_usb(sd_device * dev,NetNames * names)664 static int names_usb(sd_device *dev, NetNames *names) {
665         sd_device *usbdev;
666         char name[256], *ports, *config, *interf, *s;
667         const char *sysname;
668         size_t l;
669         int r;
670 
671         assert(dev);
672         assert(names);
673 
674         r = sd_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface", &usbdev);
675         if (r < 0)
676                 return log_device_debug_errno(dev, r, "sd_device_get_parent_with_subsystem_devtype() failed: %m");
677 
678         r = sd_device_get_sysname(usbdev, &sysname);
679         if (r < 0)
680                 return log_device_debug_errno(usbdev, r, "sd_device_get_sysname() failed: %m");
681 
682         /* get USB port number chain, configuration, interface */
683         strscpy(name, sizeof(name), sysname);
684         s = strchr(name, '-');
685         if (!s)
686                 return log_device_debug_errno(usbdev, SYNTHETIC_ERRNO(EINVAL),
687                                               "sysname \"%s\" does not have '-' in the expected place.", sysname);
688         ports = s+1;
689 
690         s = strchr(ports, ':');
691         if (!s)
692                 return log_device_debug_errno(usbdev, SYNTHETIC_ERRNO(EINVAL),
693                                               "sysname \"%s\" does not have ':' in the expected place.", sysname);
694         s[0] = '\0';
695         config = s+1;
696 
697         s = strchr(config, '.');
698         if (!s)
699                 return log_device_debug_errno(usbdev, SYNTHETIC_ERRNO(EINVAL),
700                                               "sysname \"%s\" does not have '.' in the expected place.", sysname);
701         s[0] = '\0';
702         interf = s+1;
703 
704         /* prefix every port number in the chain with "u" */
705         s = ports;
706         while ((s = strchr(s, '.')))
707                 s[0] = 'u';
708         s = names->usb_ports;
709         l = strpcpyl(&s, sizeof(names->usb_ports), "u", ports, NULL);
710 
711         /* append USB config number, suppress the common config == 1 */
712         if (!streq(config, "1"))
713                 l = strpcpyl(&s, sizeof(names->usb_ports), "c", config, NULL);
714 
715         /* append USB interface number, suppress the interface == 0 */
716         if (!streq(interf, "0"))
717                 l = strpcpyl(&s, sizeof(names->usb_ports), "i", interf, NULL);
718         if (l == 0)
719                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENAMETOOLONG),
720                                               "Generated USB name would be too long.");
721         log_device_debug(dev, "USB name identifier: ports=%.*s config=%s interface=%s → %s",
722                          (int) strlen(ports), sysname + (ports - name), config, interf, names->usb_ports);
723         names->type = NET_USB;
724         return 0;
725 }
726 
names_bcma(sd_device * dev,NetNames * names)727 static int names_bcma(sd_device *dev, NetNames *names) {
728         sd_device *bcmadev;
729         unsigned core;
730         const char *sysname;
731         int r;
732 
733         assert(dev);
734         assert(names);
735 
736         r = sd_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL, &bcmadev);
737         if (r < 0)
738                 return log_device_debug_errno(dev, r, "sd_device_get_parent_with_subsystem_devtype() failed: %m");
739 
740         r = sd_device_get_sysname(bcmadev, &sysname);
741         if (r < 0)
742                 return log_device_debug_errno(dev, r, "sd_device_get_sysname() failed: %m");
743 
744         /* bus num:core num */
745         r = sscanf(sysname, "bcma%*u:%u", &core);
746         log_device_debug(dev, "Parsing bcma device information from sysname \"%s\": %s",
747                          sysname, r == 1 ? "success" : "failure");
748         if (r != 1)
749                 return -EINVAL;
750         /* suppress the common core == 0 */
751         if (core > 0)
752                 xsprintf(names->bcma_core, "b%u", core);
753 
754         names->type = NET_BCMA;
755         log_device_debug(dev, "BCMA core identifier: core=%u → \"%s\"", core, names->bcma_core);
756         return 0;
757 }
758 
names_ccw(sd_device * dev,NetNames * names)759 static int names_ccw(sd_device *dev, NetNames *names) {
760         sd_device *cdev;
761         const char *bus_id, *subsys;
762         size_t bus_id_start, bus_id_len;
763         int r;
764 
765         assert(dev);
766         assert(names);
767 
768         /* Retrieve the associated CCW device */
769         r = sd_device_get_parent(dev, &cdev);
770         if (r < 0)
771                 return log_device_debug_errno(dev, r, "sd_device_get_parent() failed: %m");
772 
773         /* skip virtio subsystem if present */
774         cdev = skip_virtio(cdev);
775         if (!cdev)
776                 return -ENOENT;
777 
778         r = sd_device_get_subsystem(cdev, &subsys);
779         if (r < 0)
780                 return log_device_debug_errno(cdev, r, "sd_device_get_subsystem() failed: %m");
781 
782         /* Network devices are either single or grouped CCW devices */
783         if (!STR_IN_SET(subsys, "ccwgroup", "ccw"))
784                 return -ENOENT;
785         log_device_debug(dev, "Device is CCW.");
786 
787         /* Retrieve bus-ID of the CCW device.  The bus-ID uniquely
788          * identifies the network device on the Linux on System z channel
789          * subsystem.  Note that the bus-ID contains lowercase characters.
790          */
791         r = sd_device_get_sysname(cdev, &bus_id);
792         if (r < 0)
793                 return log_device_debug_errno(cdev, r, "Failed to get sysname: %m");
794 
795         /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID;
796          * alternatively, improve this check and parse and verify each bus-ID part...
797          */
798         bus_id_len = strlen(bus_id);
799         if (!IN_SET(bus_id_len, 8, 9))
800                 return log_device_debug_errno(cdev, SYNTHETIC_ERRNO(EINVAL),
801                                               "Invalid bus_id: %s", bus_id);
802 
803         /* Strip leading zeros from the bus id for aesthetic purposes. This
804          * keeps the ccw names stable, yet much shorter in general case of
805          * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is
806          * not prepended when it is zero. Preserve the last 0 for 0.0.0000.
807          */
808         bus_id_start = strspn(bus_id, ".0");
809         bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1;
810 
811         /* Store the CCW bus-ID for use as network device name */
812         if (!snprintf_ok(names->ccw_busid, sizeof(names->ccw_busid), "c%s", bus_id))
813                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENAMETOOLONG),
814                                               "Generated CCW name would be too long.");
815         names->type = NET_CCW;
816         log_device_debug(dev, "CCW identifier: ccw_busid=%s → \"%s\"", bus_id, names->ccw_busid);
817         return 0;
818 }
819 
names_mac(sd_device * dev,const LinkInfo * info)820 static int names_mac(sd_device *dev, const LinkInfo *info) {
821         const char *s;
822         unsigned i;
823         int r;
824 
825         assert(dev);
826         assert(info);
827 
828         /* The persistent part of a hardware address of an InfiniBand NIC is 8 bytes long. We cannot
829          * fit this much in an iface name.
830          * TODO: but it can be used as alternative names?? */
831         if (info->iftype == ARPHRD_INFINIBAND)
832                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EOPNOTSUPP),
833                                               "Not generating MAC name for infiniband device.");
834         if (info->hw_addr.length != 6)
835                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EOPNOTSUPP),
836                                               "Not generating MAC name for device with MAC address of length %zu.",
837                                               info->hw_addr.length);
838 
839         /* check for NET_ADDR_PERM, skip random MAC addresses */
840         r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s);
841         if (r < 0)
842                 return log_device_debug_errno(dev, r, "Failed to read addr_assign_type: %m");
843         r = safe_atou(s, &i);
844         if (r < 0)
845                 return log_device_debug_errno(dev, r, "Failed to parse addr_assign_type: %m");
846         if (i != NET_ADDR_PERM)
847                 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
848                                               "addr_assign_type=%d, MAC address is not permanent.", i);
849         return 0;
850 }
851 
names_netdevsim(sd_device * dev,const LinkInfo * info,NetNames * names)852 static int names_netdevsim(sd_device *dev, const LinkInfo *info, NetNames *names) {
853         sd_device *netdevsimdev;
854         const char *sysname;
855         unsigned addr;
856         int r;
857 
858         if (!naming_scheme_has(NAMING_NETDEVSIM))
859                 return 0;
860 
861         assert(dev);
862         assert(info);
863         assert(names);
864 
865         if (isempty(info->phys_port_name))
866                 return -EINVAL;
867 
868         r = sd_device_get_parent_with_subsystem_devtype(dev, "netdevsim", NULL, &netdevsimdev);
869         if (r < 0)
870                 return r;
871         r = sd_device_get_sysname(netdevsimdev, &sysname);
872         if (r < 0)
873                 return r;
874 
875         if (sscanf(sysname, "netdevsim%u", &addr) != 1)
876                 return -EINVAL;
877 
878         if (!snprintf_ok(names->netdevsim_path, sizeof(names->netdevsim_path), "i%un%s", addr, info->phys_port_name))
879                 return -ENOBUFS;
880 
881         names->type = NET_NETDEVSIM;
882 
883         return 0;
884 }
885 
names_xen(sd_device * dev,NetNames * names)886 static int names_xen(sd_device *dev, NetNames *names) {
887         sd_device *parent;
888         unsigned id;
889         const char *syspath, *subsystem, *p, *p2;
890         int r;
891 
892         assert(dev);
893         assert(names);
894 
895         if (!naming_scheme_has(NAMING_XEN_VIF))
896                 return 0;
897 
898         /* check if our direct parent is a Xen VIF device with no other bus in-between */
899         r = sd_device_get_parent(dev, &parent);
900         if (r < 0)
901                 return r;
902 
903         /* Do an exact-match on subsystem "xen". This will miss on "xen-backend" on
904          * purpose as the VIFs on the backend (dom0) have their own naming scheme
905          * which we don't want to affect
906          */
907         r = sd_device_get_subsystem(parent, &subsystem);
908         if (r < 0)
909                 return r;
910         if (!streq("xen", subsystem))
911                 return -ENOENT;
912 
913         /* Use the vif-n name to extract "n" */
914         r = sd_device_get_syspath(dev, &syspath);
915         if (r < 0)
916                 return r;
917 
918         p = path_startswith(syspath, "/sys/devices/");
919         if (!p)
920                 return -ENOENT;
921         p = startswith(p, "vif-");
922         if (!p)
923                 return -ENOENT;
924         p2 = strchr(p, '/');
925         if (!p2)
926                 return -ENOENT;
927         p = strndupa_safe(p, p2 - p);
928         if (!p)
929                 return -ENOENT;
930         r = safe_atou_full(p, SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_ZERO |
931                            SAFE_ATO_REFUSE_LEADING_WHITESPACE | 10, &id);
932         if (r < 0)
933                 return r;
934         xsprintf(names->xen_slot, "X%u", id);
935         names->type = NET_XENVIF;
936         return 0;
937 }
938 
939 /* IEEE Organizationally Unique Identifier vendor string */
ieee_oui(sd_device * dev,const LinkInfo * info,bool test)940 static int ieee_oui(sd_device *dev, const LinkInfo *info, bool test) {
941         char str[32];
942 
943         assert(dev);
944         assert(info);
945 
946         if (info->hw_addr.length != 6)
947                 return -EOPNOTSUPP;
948 
949         /* skip commonly misused 00:00:00 (Xerox) prefix */
950         if (info->hw_addr.bytes[0] == 0 &&
951             info->hw_addr.bytes[1] == 0 &&
952             info->hw_addr.bytes[2] == 0)
953                 return -EINVAL;
954 
955         xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X",
956                  info->hw_addr.bytes[0],
957                  info->hw_addr.bytes[1],
958                  info->hw_addr.bytes[2],
959                  info->hw_addr.bytes[3],
960                  info->hw_addr.bytes[4],
961                  info->hw_addr.bytes[5]);
962         return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
963 }
964 
builtin_net_id(sd_device * dev,sd_netlink ** rtnl,int argc,char * argv[],bool test)965 static int builtin_net_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
966         _cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
967         const char *devtype, *prefix = "en";
968         NetNames names = {};
969         int ifindex, r;
970 
971         r = sd_device_get_ifindex(dev, &ifindex);
972         if (r < 0)
973                 return r;
974 
975         r = link_info_get(rtnl, ifindex, &info);
976         if (r < 0)
977                 return r;
978 
979         if (!info.phys_port_name_supported) {
980                 const char *s;
981 
982                 r = sd_device_get_sysattr_value(dev, "phys_port_name", &s);
983                 if (r >= 0) {
984                         info.phys_port_name = strdup(s);
985                         if (!info.phys_port_name)
986                                 return log_oom();
987                 }
988         }
989 
990         r = device_cache_sysattr_from_link_info(dev, &info);
991         if (r < 0)
992                 return r;
993 
994         /* skip stacked devices, like VLANs, ... */
995         if (info.ifindex != (int) info.iflink)
996                 return 0;
997 
998         /* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */
999         switch (info.iftype) {
1000         case ARPHRD_ETHER:
1001                 prefix = "en";
1002                 break;
1003         case ARPHRD_INFINIBAND:
1004                 if (naming_scheme_has(NAMING_INFINIBAND))
1005                         prefix = "ib";
1006                 else
1007                         return 0;
1008                 break;
1009         case ARPHRD_SLIP:
1010                 prefix = "sl";
1011                 break;
1012         default:
1013                 return 0;
1014         }
1015 
1016         if (sd_device_get_devtype(dev, &devtype) >= 0) {
1017                 if (streq("wlan", devtype))
1018                         prefix = "wl";
1019                 else if (streq("wwan", devtype))
1020                         prefix = "ww";
1021         }
1022 
1023         udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
1024 
1025         if (names_mac(dev, &info) >= 0) {
1026                 char str[ALTIFNAMSIZ];
1027 
1028                 xsprintf(str, "%sx%s", prefix, HW_ADDR_TO_STR_FULL(&info.hw_addr, HW_ADDR_TO_STRING_NO_COLON));
1029                 udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
1030                 log_device_debug(dev, "MAC address identifier: hw_addr=%s → %s",
1031                                  HW_ADDR_TO_STR(&info.hw_addr), str + strlen(prefix));
1032 
1033                 ieee_oui(dev, &info, test);
1034         }
1035 
1036         /* get path names for Linux on System z network devices */
1037         if (names_ccw(dev, &names) >= 0 && names.type == NET_CCW) {
1038                 char str[ALTIFNAMSIZ];
1039 
1040                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.ccw_busid))
1041                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
1042                 return 0;
1043         }
1044 
1045         /* get ibmveth/ibmvnic slot-based names. */
1046         if (names_vio(dev, &names) >= 0 && names.type == NET_VIO) {
1047                 char str[ALTIFNAMSIZ];
1048 
1049                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.vio_slot))
1050                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
1051                 return 0;
1052         }
1053 
1054         /* get ACPI path names for ARM64 platform devices */
1055         if (names_platform(dev, &names, test) >= 0 && names.type == NET_PLATFORM) {
1056                 char str[ALTIFNAMSIZ];
1057 
1058                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.platform_path))
1059                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
1060                 return 0;
1061         }
1062 
1063         /* get netdevsim path names */
1064         if (names_netdevsim(dev, &info, &names) >= 0 && names.type == NET_NETDEVSIM) {
1065                 char str[ALTIFNAMSIZ];
1066 
1067                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.netdevsim_path))
1068                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
1069 
1070                 return 0;
1071         }
1072 
1073         /* get xen vif "slot" based names. */
1074         if (names_xen(dev, &names) >= 0 && names.type == NET_XENVIF) {
1075                 char str[ALTIFNAMSIZ];
1076 
1077                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.xen_slot))
1078                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
1079                 return 0;
1080         }
1081 
1082         /* get PCI based path names, we compose only PCI based paths */
1083         if (names_pci(dev, &info, &names) < 0)
1084                 return 0;
1085 
1086         /* plain PCI device */
1087         if (names.type == NET_PCI) {
1088                 char str[ALTIFNAMSIZ];
1089 
1090                 if (names.pci_onboard[0] &&
1091                     snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_onboard))
1092                         udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
1093 
1094                 if (names.pci_onboard_label &&
1095                     snprintf_ok(str, sizeof str, "%s%s",
1096                                 naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
1097                                 names.pci_onboard_label))
1098                         udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
1099 
1100                 if (names.pci_path[0] &&
1101                     snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_path))
1102                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
1103 
1104                 if (names.pci_slot[0] &&
1105                     snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_slot))
1106                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
1107                 return 0;
1108         }
1109 
1110         /* USB device */
1111         if (names_usb(dev, &names) >= 0 && names.type == NET_USB) {
1112                 char str[ALTIFNAMSIZ];
1113 
1114                 if (names.pci_path[0] &&
1115                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.usb_ports))
1116                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
1117 
1118                 if (names.pci_slot[0] &&
1119                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.usb_ports))
1120                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
1121                 return 0;
1122         }
1123 
1124         /* Broadcom bus */
1125         if (names_bcma(dev, &names) >= 0 && names.type == NET_BCMA) {
1126                 char str[ALTIFNAMSIZ];
1127 
1128                 if (names.pci_path[0] &&
1129                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.bcma_core))
1130                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
1131 
1132                 if (names.pci_slot[0] &&
1133                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core))
1134                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
1135                 return 0;
1136         }
1137 
1138         return 0;
1139 }
1140 
builtin_net_id_init(void)1141 static int builtin_net_id_init(void) {
1142         /* Load naming scheme here to suppress log messages in workers. */
1143         naming_scheme();
1144         return 0;
1145 }
1146 
1147 const UdevBuiltin udev_builtin_net_id = {
1148         .name = "net_id",
1149         .cmd = builtin_net_id,
1150         .init = builtin_net_id_init,
1151         .help = "Network device properties",
1152 };
1153