]>
Commit | Line | Data |
---|---|---|
a660c63c KS |
1 | /*** |
2 | This file is part of systemd. | |
3 | ||
4 | Copyright 2012 Kay Sievers <kay@vrfy.org> | |
5 | ||
6 | systemd is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU Lesser General Public License as published by | |
8 | the Free Software Foundation; either version 2.1 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | systemd is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public License | |
17 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
18 | ***/ | |
19 | ||
d23965a6 KS |
20 | /* |
21 | * eno<index> -- ethernet on-board | |
22 | * ID_NET_NAME_FIRMWARE=eno1 | |
23 | * | |
24 | * enp<pci bus number>s<slot>f<function> -- physical location/path | |
25 | * ID_NET_NAME_PATH=enp19s0f0 | |
26 | * | |
27 | * enm<MAC address> -- MAC address | |
28 | * ID_NET_NAME_MAC=enxf0def180d479 | |
29 | */ | |
30 | ||
a660c63c KS |
31 | #include <stdio.h> |
32 | #include <stdlib.h> | |
33 | #include <stdarg.h> | |
34 | #include <unistd.h> | |
35 | #include <string.h> | |
36 | #include <errno.h> | |
37 | ||
38 | #include "udev.h" | |
39 | ||
d23965a6 KS |
40 | static int dev_pci(struct udev_device *dev, const char *prefix, bool test) { |
41 | struct udev_device *d; | |
42 | unsigned int bus; | |
43 | unsigned int slot; | |
44 | unsigned int func; | |
45 | const char *index; | |
46 | int err; | |
a660c63c | 47 | |
d23965a6 KS |
48 | /* skip other buses than direct PCI parents */ |
49 | d = udev_device_get_parent(dev); | |
50 | if (!d || !streq("pci", udev_device_get_subsystem(d))) | |
a660c63c KS |
51 | return -ENOENT; |
52 | ||
01d183dd KS |
53 | /* ACPI _SUN -- slot user number */ |
54 | index = udev_device_get_sysattr_value(d, "acpi_index"); | |
55 | /* SMBIOS type 41 -- Onboard Devices Extended Information */ | |
56 | if (!index) | |
57 | index = udev_device_get_sysattr_value(d, "index"); | |
d23965a6 KS |
58 | if (index) { |
59 | unsigned int idx; | |
60 | ||
61 | idx = strtoul(index, NULL, 0); | |
62 | if (idx > 0) { | |
63 | const char *label; | |
64 | char s[16]; | |
65 | ||
66 | snprintf(s, sizeof(s), "%so%d", prefix, idx); | |
67 | udev_builtin_add_property(dev, test, "ID_NET_NAME_FIRMWARE", s); | |
68 | ||
69 | label = udev_device_get_sysattr_value(d, "label"); | |
70 | if (label) | |
71 | udev_builtin_add_property(dev, test, "ID_NET_LABEL_FIRMWARE", label); | |
72 | } | |
73 | } | |
74 | ||
75 | /* compose a name based on the PCI bus location */ | |
76 | if (sscanf(udev_device_get_sysname(d), "0000:%x:%x.%d", &bus, &slot, &func) == 3) { | |
77 | char str[16]; | |
78 | ||
79 | snprintf(str, sizeof(str), "%sp%ds%df%d", prefix, bus, slot, func); | |
80 | err = udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); | |
81 | if (err < 0) | |
82 | return err; | |
83 | } | |
84 | return 0; | |
85 | } | |
86 | ||
87 | static int dev_mac(struct udev_device *dev, const char *prefix, bool test) { | |
88 | const char *s; | |
89 | unsigned int i; | |
90 | unsigned int a1, a2, a3, a4, a5, a6; | |
91 | char str[16]; | |
92 | int err; | |
93 | ||
94 | /* check for NET_ADDR_PERM, skip random MAC addresses */ | |
95 | s = udev_device_get_sysattr_value(dev, "addr_assign_type"); | |
96 | if (!s) | |
97 | return EXIT_FAILURE; | |
98 | i = strtoul(s, NULL, 0); | |
99 | if (i != 0) | |
100 | return 0; | |
101 | ||
102 | s = udev_device_get_sysattr_value(dev, "address"); | |
103 | if (!s) | |
104 | return -ENOENT; | |
105 | if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) | |
106 | return -EINVAL; | |
107 | ||
108 | /* skip empty MAC addresses */ | |
109 | if (a1 + a2 + a3 + a4 + a5 + a6 == 0) | |
a660c63c KS |
110 | return -EINVAL; |
111 | ||
d23965a6 KS |
112 | /* add IEEE Organizationally Unique Identifier */ |
113 | snprintf(str, sizeof(str), "OUI:%X%X%X", a1, a2, a3); | |
114 | udev_builtin_hwdb_lookup(dev, str, test); | |
115 | ||
116 | snprintf(str, sizeof(str), "%sx%x%x%x%x%x%x", prefix, a1, a2, a3, a4, a5, a6); | |
117 | err = udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str); | |
118 | if (err < 0) | |
119 | return err; | |
120 | return 0; | |
a660c63c KS |
121 | } |
122 | ||
123 | static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) { | |
d23965a6 KS |
124 | const char *s; |
125 | unsigned int i; | |
126 | const char *devtype; | |
127 | const char *prefix = "en"; | |
128 | ||
129 | /* handle only ARPHRD_ETHER devices */ | |
130 | s = udev_device_get_sysattr_value(dev, "type"); | |
131 | if (!s) | |
132 | return EXIT_FAILURE; | |
133 | i = strtoul(s, NULL, 0); | |
134 | if (i != 1) | |
135 | return 0; | |
136 | ||
137 | devtype = udev_device_get_devtype(dev); | |
138 | if (devtype) { | |
139 | if (streq("wlan", devtype)) | |
140 | prefix = "wl"; | |
141 | else if (streq("wwan", devtype)) | |
142 | prefix = "ww"; | |
143 | } | |
144 | ||
145 | dev_pci(dev, prefix, test); | |
146 | dev_mac(dev, prefix, test); | |
a660c63c KS |
147 | return EXIT_SUCCESS; |
148 | } | |
149 | ||
150 | const struct udev_builtin udev_builtin_net_id = { | |
151 | .name = "net_id", | |
152 | .cmd = builtin_net_id, | |
153 | .help = "network device properties", | |
154 | }; |