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