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