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