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