File: | build-scan/../src/udev/net/link-config.c |
Warning: | line 513, column 1 Potential leak of memory pointed to by 'en' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <netinet/ether.h> | |||
4 | ||||
5 | #include "sd-netlink.h" | |||
6 | ||||
7 | #include "alloc-util.h" | |||
8 | #include "conf-files.h" | |||
9 | #include "conf-parser.h" | |||
10 | #include "ethtool-util.h" | |||
11 | #include "fd-util.h" | |||
12 | #include "libudev-private.h" | |||
13 | #include "link-config.h" | |||
14 | #include "log.h" | |||
15 | #include "missing.h" | |||
16 | #include "netlink-util.h" | |||
17 | #include "network-internal.h" | |||
18 | #include "parse-util.h" | |||
19 | #include "path-util.h" | |||
20 | #include "proc-cmdline.h" | |||
21 | #include "random-util.h" | |||
22 | #include "stat-util.h" | |||
23 | #include "string-table.h" | |||
24 | #include "string-util.h" | |||
25 | #include "strv.h" | |||
26 | #include "util.h" | |||
27 | ||||
28 | struct link_config_ctx { | |||
29 | LIST_HEAD(link_config, links)link_config *links; | |||
30 | ||||
31 | int ethtool_fd; | |||
32 | ||||
33 | bool_Bool enable_name_policy; | |||
34 | ||||
35 | sd_netlink *rtnl; | |||
36 | ||||
37 | usec_t link_dirs_ts_usec; | |||
38 | }; | |||
39 | ||||
40 | static const char* const link_dirs[] = { | |||
41 | "/etc/systemd/network", | |||
42 | "/run/systemd/network", | |||
43 | "/usr/lib/systemd/network", | |||
44 | #if HAVE_SPLIT_USR0 | |||
45 | "/lib/systemd/network", | |||
46 | #endif | |||
47 | NULL((void*)0)}; | |||
48 | ||||
49 | static void link_config_free(link_config *link) { | |||
50 | if (!link) | |||
51 | return; | |||
52 | ||||
53 | free(link->filename); | |||
54 | ||||
55 | set_free_free(link->match_mac); | |||
56 | strv_free(link->match_path); | |||
57 | strv_free(link->match_driver); | |||
58 | strv_free(link->match_type); | |||
59 | free(link->match_name); | |||
60 | free(link->match_host); | |||
61 | free(link->match_virt); | |||
62 | free(link->match_kernel_cmdline); | |||
63 | free(link->match_kernel_version); | |||
64 | free(link->match_arch); | |||
65 | ||||
66 | free(link->description); | |||
67 | free(link->mac); | |||
68 | free(link->name_policy); | |||
69 | free(link->name); | |||
70 | free(link->alias); | |||
71 | ||||
72 | free(link); | |||
73 | } | |||
74 | ||||
75 | DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free)static inline void link_config_freep(link_config* *p) { if (* p) link_config_free(*p); }; | |||
76 | ||||
77 | static void link_configs_free(link_config_ctx *ctx) { | |||
78 | link_config *link, *link_next; | |||
79 | ||||
80 | if (!ctx) | |||
81 | return; | |||
82 | ||||
83 | LIST_FOREACH_SAFE(links, link, link_next, ctx->links)for ((link) = (ctx->links); (link) && (((link_next ) = (link)->links_next), 1); (link) = (link_next)) | |||
84 | link_config_free(link); | |||
85 | } | |||
86 | ||||
87 | void link_config_ctx_free(link_config_ctx *ctx) { | |||
88 | if (!ctx) | |||
89 | return; | |||
90 | ||||
91 | safe_close(ctx->ethtool_fd); | |||
92 | ||||
93 | sd_netlink_unref(ctx->rtnl); | |||
94 | ||||
95 | link_configs_free(ctx); | |||
96 | ||||
97 | free(ctx); | |||
98 | ||||
99 | return; | |||
100 | } | |||
101 | ||||
102 | DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free)static inline void link_config_ctx_freep(link_config_ctx* *p) { if (*p) link_config_ctx_free(*p); }; | |||
103 | ||||
104 | int link_config_ctx_new(link_config_ctx **ret) { | |||
105 | _cleanup_(link_config_ctx_freep)__attribute__((cleanup(link_config_ctx_freep))) link_config_ctx *ctx = NULL((void*)0); | |||
106 | ||||
107 | if (!ret) | |||
108 | return -EINVAL22; | |||
109 | ||||
110 | ctx = new0(link_config_ctx, 1)((link_config_ctx*) calloc((1), sizeof(link_config_ctx))); | |||
111 | if (!ctx) | |||
112 | return -ENOMEM12; | |||
113 | ||||
114 | LIST_HEAD_INIT(ctx->links)do { (ctx->links) = ((void*)0); } while (0); | |||
115 | ||||
116 | ctx->ethtool_fd = -1; | |||
117 | ||||
118 | ctx->enable_name_policy = true1; | |||
119 | ||||
120 | *ret = TAKE_PTR(ctx)({ typeof(ctx) _ptr_ = (ctx); (ctx) = ((void*)0); _ptr_; }); | |||
121 | ||||
122 | return 0; | |||
123 | } | |||
124 | ||||
125 | static int load_link(link_config_ctx *ctx, const char *filename) { | |||
126 | _cleanup_(link_config_freep)__attribute__((cleanup(link_config_freep))) link_config *link = NULL((void*)0); | |||
127 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *file = NULL((void*)0); | |||
128 | int r; | |||
129 | ||||
130 | assert(ctx)do { if ((__builtin_expect(!!(!(ctx)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("ctx"), "../src/udev/net/link-config.c", 130 , __PRETTY_FUNCTION__); } while (0); | |||
131 | assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("filename"), "../src/udev/net/link-config.c" , 131, __PRETTY_FUNCTION__); } while (0); | |||
132 | ||||
133 | file = fopen(filename, "re"); | |||
134 | if (!file) { | |||
135 | if (errno(*__errno_location ()) == ENOENT2) | |||
136 | return 0; | |||
137 | else | |||
138 | return -errno(*__errno_location ()); | |||
139 | } | |||
140 | ||||
141 | if (null_or_empty_fd(fileno(file))) { | |||
142 | log_debug("Skipping empty file: %s", filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 142, __func__, "Skipping empty file: %s" , filename) : -abs(_e); }); | |||
143 | return 0; | |||
144 | } | |||
145 | ||||
146 | link = new0(link_config, 1)((link_config*) calloc((1), sizeof(link_config))); | |||
147 | if (!link) | |||
148 | return log_oom()log_oom_internal(LOG_REALM_UDEV, "../src/udev/net/link-config.c" , 148, __func__); | |||
149 | ||||
150 | link->mac_policy = _MACPOLICY_INVALID; | |||
151 | link->wol = _WOL_INVALID; | |||
152 | link->duplex = _DUP_INVALID; | |||
153 | link->port = _NET_DEV_PORT_INVALID; | |||
154 | link->autonegotiation = -1; | |||
155 | ||||
156 | memset(&link->features, 0xFF, sizeof(link->features)); | |||
157 | ||||
158 | r = config_parse(NULL((void*)0), filename, file, | |||
159 | "Match\0Link\0Ethernet\0", | |||
160 | config_item_perf_lookup, link_config_gperf_lookup, | |||
161 | CONFIG_PARSE_WARN, link); | |||
162 | if (r < 0) | |||
163 | return r; | |||
164 | else | |||
165 | log_debug("Parsed configuration file %s", filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 165, __func__, "Parsed configuration file %s" , filename) : -abs(_e); }); | |||
166 | ||||
167 | if (link->speed > UINT_MAX(2147483647 *2U +1U)) | |||
168 | return -ERANGE34; | |||
169 | ||||
170 | link->filename = strdup(filename); | |||
171 | if (!link->filename) | |||
172 | return log_oom()log_oom_internal(LOG_REALM_UDEV, "../src/udev/net/link-config.c" , 172, __func__); | |||
173 | ||||
174 | LIST_PREPEND(links, ctx->links, link)do { typeof(*(ctx->links)) **_head = &(ctx->links), *_item = (link); do { if ((__builtin_expect(!!(!(_item)),0)) ) log_assert_failed_realm(LOG_REALM_UDEV, ("_item"), "../src/udev/net/link-config.c" , 174, __PRETTY_FUNCTION__); } while (0); if ((_item->links_next = *_head)) _item->links_next->links_prev = _item; _item ->links_prev = ((void*)0); *_head = _item; } while (0); | |||
175 | link = NULL((void*)0); | |||
176 | ||||
177 | return 0; | |||
178 | } | |||
179 | ||||
180 | static bool_Bool enable_name_policy(void) { | |||
181 | bool_Bool b; | |||
182 | ||||
183 | return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b; | |||
184 | } | |||
185 | ||||
186 | int link_config_load(link_config_ctx *ctx) { | |||
187 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **files; | |||
188 | char **f; | |||
189 | int r; | |||
190 | ||||
191 | link_configs_free(ctx); | |||
192 | ||||
193 | if (!enable_name_policy()) { | |||
194 | ctx->enable_name_policy = false0; | |||
195 | log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.")({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 195, __func__, "Network interface NamePolicy= disabled on kernel command line, ignoring." ) : -abs(_e); }); | |||
196 | } | |||
197 | ||||
198 | /* update timestamp */ | |||
199 | paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true1); | |||
200 | ||||
201 | r = conf_files_list_strv(&files, ".link", NULL((void*)0), 0, link_dirs); | |||
202 | if (r < 0) | |||
203 | return log_error_errno(r, "failed to enumerate link files: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 203, __func__, "failed to enumerate link files: %m" ) : -abs(_e); }); | |||
204 | ||||
205 | STRV_FOREACH_BACKWARDS(f, files)for (f = ({ char **_l = files; _l ? _l + strv_length(_l) - 1U : ((void*)0); }); (files) && ((f) >= (files)); (f )--) { | |||
206 | r = load_link(ctx, *f); | |||
207 | if (r < 0) | |||
208 | return r; | |||
209 | } | |||
210 | ||||
211 | return 0; | |||
212 | } | |||
213 | ||||
214 | bool_Bool link_config_should_reload(link_config_ctx *ctx) { | |||
215 | return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false0); | |||
216 | } | |||
217 | ||||
218 | int link_config_get(link_config_ctx *ctx, struct udev_device *device, | |||
219 | link_config **ret) { | |||
220 | link_config *link; | |||
221 | ||||
222 | assert(ctx)do { if ((__builtin_expect(!!(!(ctx)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("ctx"), "../src/udev/net/link-config.c", 222 , __PRETTY_FUNCTION__); } while (0); | |||
223 | assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("device"), "../src/udev/net/link-config.c", 223, __PRETTY_FUNCTION__); } while (0); | |||
224 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("ret"), "../src/udev/net/link-config.c", 224 , __PRETTY_FUNCTION__); } while (0); | |||
225 | ||||
226 | LIST_FOREACH(links, link, ctx->links)for ((link) = (ctx->links); (link); (link) = (link)->links_next ) { | |||
227 | const char* attr_value; | |||
228 | ||||
229 | attr_value = udev_device_get_sysattr_value(device, "address"); | |||
230 | ||||
231 | if (net_match_config(link->match_mac, link->match_path, link->match_driver, | |||
232 | link->match_type, link->match_name, link->match_host, | |||
233 | link->match_virt, link->match_kernel_cmdline, | |||
234 | link->match_kernel_version, link->match_arch, | |||
235 | attr_value ? ether_aton(attr_value) : NULL((void*)0), | |||
236 | udev_device_get_property_value(device, "ID_PATH"), | |||
237 | udev_device_get_driver(udev_device_get_parent(device)), | |||
238 | udev_device_get_property_value(device, "ID_NET_DRIVER"), | |||
239 | udev_device_get_devtype(device), | |||
240 | udev_device_get_sysname(device))) { | |||
241 | if (link->match_name) { | |||
242 | unsigned char name_assign_type = NET_NAME_UNKNOWN0; | |||
243 | ||||
244 | attr_value = udev_device_get_sysattr_value(device, "name_assign_type"); | |||
245 | if (attr_value) | |||
246 | (void) safe_atou8(attr_value, &name_assign_type); | |||
247 | ||||
248 | if (name_assign_type == NET_NAME_ENUM1) { | |||
249 | log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 250, __func__, "Config file %s applies to device based on potentially unpredictable interface name '%s'" , link->filename, udev_device_get_sysname(device)) : -abs( _e); }) | |||
250 | link->filename, udev_device_get_sysname(device))({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 250, __func__, "Config file %s applies to device based on potentially unpredictable interface name '%s'" , link->filename, udev_device_get_sysname(device)) : -abs( _e); }); | |||
251 | *ret = link; | |||
252 | ||||
253 | return 0; | |||
254 | } else if (name_assign_type == NET_NAME_RENAMED4) { | |||
255 | log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 256, __func__, "Config file %s matches device based on renamed interface name '%s', ignoring" , link->filename, udev_device_get_sysname(device)) : -abs( _e); }) | |||
256 | link->filename, udev_device_get_sysname(device))({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 256, __func__, "Config file %s matches device based on renamed interface name '%s', ignoring" , link->filename, udev_device_get_sysname(device)) : -abs( _e); }); | |||
257 | ||||
258 | continue; | |||
259 | } | |||
260 | } | |||
261 | ||||
262 | log_debug("Config file %s applies to device %s",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 263, __func__, "Config file %s applies to device %s" , link->filename, udev_device_get_sysname(device)) : -abs( _e); }) | |||
263 | link->filename, udev_device_get_sysname(device))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 263, __func__, "Config file %s applies to device %s" , link->filename, udev_device_get_sysname(device)) : -abs( _e); }); | |||
264 | ||||
265 | *ret = link; | |||
266 | ||||
267 | return 0; | |||
268 | } | |||
269 | } | |||
270 | ||||
271 | *ret = NULL((void*)0); | |||
272 | ||||
273 | return -ENOENT2; | |||
274 | } | |||
275 | ||||
276 | static bool_Bool mac_is_random(struct udev_device *device) { | |||
277 | const char *s; | |||
278 | unsigned type; | |||
279 | int r; | |||
280 | ||||
281 | /* if we can't get the assign type, assume it is not random */ | |||
282 | s = udev_device_get_sysattr_value(device, "addr_assign_type"); | |||
283 | if (!s) | |||
284 | return false0; | |||
285 | ||||
286 | r = safe_atou(s, &type); | |||
287 | if (r < 0) | |||
288 | return false0; | |||
289 | ||||
290 | return type == NET_ADDR_RANDOM1; | |||
291 | } | |||
292 | ||||
293 | static bool_Bool should_rename(struct udev_device *device, bool_Bool respect_predictable) { | |||
294 | const char *s; | |||
295 | unsigned type; | |||
296 | int r; | |||
297 | ||||
298 | /* if we can't get the assgin type, assume we should rename */ | |||
299 | s = udev_device_get_sysattr_value(device, "name_assign_type"); | |||
300 | if (!s) | |||
301 | return true1; | |||
302 | ||||
303 | r = safe_atou(s, &type); | |||
304 | if (r < 0) | |||
305 | return true1; | |||
306 | ||||
307 | switch (type) { | |||
308 | case NET_NAME_USER3: | |||
309 | /* these were already named by userspace, do not touch again */ | |||
310 | return false0; | |||
311 | case NET_NAME_PREDICTABLE2: | |||
312 | /* the kernel claims to have given a predictable name */ | |||
313 | if (respect_predictable) | |||
314 | return false0; | |||
315 | _fallthrough_; | |||
316 | case NET_NAME_ENUM1: | |||
317 | default: | |||
318 | /* the name is known to be bad, or of an unknown type */ | |||
319 | return true1; | |||
320 | } | |||
321 | } | |||
322 | ||||
323 | static int get_mac(struct udev_device *device, bool_Bool want_random, | |||
324 | struct ether_addr *mac) { | |||
325 | int r; | |||
326 | ||||
327 | if (want_random) | |||
328 | random_bytes(mac->ether_addr_octet, ETH_ALEN6); | |||
329 | else { | |||
330 | uint64_t result; | |||
331 | ||||
332 | r = net_get_unique_predictable_data(device, &result); | |||
333 | if (r < 0) | |||
334 | return r; | |||
335 | ||||
336 | assert_cc(ETH_ALEN <= sizeof(result))GCC diagnostic push
; GCC diagnostic ignored "-Wdeclaration-after-statement" ; struct _assert_struct_17 { char x[(6 <= sizeof(result)) ? 0 : -1]; }; GCC diagnostic pop ; | |||
337 | memcpy(mac->ether_addr_octet, &result, ETH_ALEN6); | |||
338 | } | |||
339 | ||||
340 | /* see eth_random_addr in the kernel */ | |||
341 | mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ | |||
342 | mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ | |||
343 | ||||
344 | return 0; | |||
345 | } | |||
346 | ||||
347 | int link_config_apply(link_config_ctx *ctx, link_config *config, | |||
348 | struct udev_device *device, const char **name) { | |||
349 | bool_Bool respect_predictable = false0; | |||
350 | struct ether_addr generated_mac; | |||
351 | struct ether_addr *mac = NULL((void*)0); | |||
352 | const char *new_name = NULL((void*)0); | |||
353 | const char *old_name; | |||
354 | unsigned speed; | |||
355 | int r, ifindex; | |||
356 | ||||
357 | assert(ctx)do { if ((__builtin_expect(!!(!(ctx)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("ctx"), "../src/udev/net/link-config.c", 357 , __PRETTY_FUNCTION__); } while (0); | |||
358 | assert(config)do { if ((__builtin_expect(!!(!(config)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("config"), "../src/udev/net/link-config.c", 358, __PRETTY_FUNCTION__); } while (0); | |||
359 | assert(device)do { if ((__builtin_expect(!!(!(device)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("device"), "../src/udev/net/link-config.c", 359, __PRETTY_FUNCTION__); } while (0); | |||
360 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("name"), "../src/udev/net/link-config.c", 360 , __PRETTY_FUNCTION__); } while (0); | |||
361 | ||||
362 | old_name = udev_device_get_sysname(device); | |||
363 | if (!old_name) | |||
364 | return -EINVAL22; | |||
365 | ||||
366 | r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config); | |||
367 | if (r < 0) { | |||
368 | ||||
369 | if (config->port != _NET_DEV_PORT_INVALID) | |||
370 | log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 370, __func__, "Could not set port (%s) of %s: %m" , port_to_string(config->port), old_name) : -abs(_e); }); | |||
371 | ||||
372 | speed = DIV_ROUND_UP(config->speed, 1000000)({ const typeof((config->speed)) __unique_prefix_X18 = ((config ->speed)); const typeof((1000000)) __unique_prefix_Y19 = ( (1000000)); (__unique_prefix_X18 / __unique_prefix_Y19 + !!(__unique_prefix_X18 % __unique_prefix_Y19)); }); | |||
373 | if (r == -EOPNOTSUPP95) | |||
374 | r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex); | |||
375 | ||||
376 | if (r < 0) | |||
377 | log_warning_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 378, __func__, "Could not set speed or duplex of %s to %u Mbps (%s): %m" , old_name, speed, duplex_to_string(config->duplex)) : -abs (_e); }) | |||
378 | old_name, speed, duplex_to_string(config->duplex))({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 378, __func__, "Could not set speed or duplex of %s to %u Mbps (%s): %m" , old_name, speed, duplex_to_string(config->duplex)) : -abs (_e); }); | |||
379 | } | |||
380 | ||||
381 | r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol); | |||
382 | if (r < 0) | |||
383 | log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 384, __func__, "Could not set WakeOnLan of %s to %s: %m" , old_name, wol_to_string(config->wol)) : -abs(_e); }) | |||
384 | old_name, wol_to_string(config->wol))({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 384, __func__, "Could not set WakeOnLan of %s to %s: %m" , old_name, wol_to_string(config->wol)) : -abs(_e); }); | |||
385 | ||||
386 | r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features); | |||
387 | if (r < 0) | |||
388 | log_warning_errno(r, "Could not set offload features of %s: %m", old_name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 388, __func__, "Could not set offload features of %s: %m" , old_name) : -abs(_e); }); | |||
389 | ||||
390 | if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) { | |||
391 | r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels); | |||
392 | if (r < 0) | |||
393 | log_warning_errno(r, "Could not set channels of %s: %m", old_name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 393, __func__, "Could not set channels of %s: %m" , old_name) : -abs(_e); }); | |||
394 | } | |||
395 | ||||
396 | ifindex = udev_device_get_ifindex(device); | |||
397 | if (ifindex <= 0) { | |||
398 | log_warning("Could not find ifindex")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/net/link-config.c", 398, __func__, "Could not find ifindex" ) : -abs(_e); }); | |||
399 | return -ENODEV19; | |||
400 | } | |||
401 | ||||
402 | if (ctx->enable_name_policy && config->name_policy) { | |||
403 | NamePolicy *policy; | |||
404 | ||||
405 | for (policy = config->name_policy; | |||
406 | !new_name && *policy != _NAMEPOLICY_INVALID; policy++) { | |||
407 | switch (*policy) { | |||
408 | case NAMEPOLICY_KERNEL: | |||
409 | respect_predictable = true1; | |||
410 | break; | |||
411 | case NAMEPOLICY_DATABASE: | |||
412 | new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE"); | |||
413 | break; | |||
414 | case NAMEPOLICY_ONBOARD: | |||
415 | new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD"); | |||
416 | break; | |||
417 | case NAMEPOLICY_SLOT: | |||
418 | new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT"); | |||
419 | break; | |||
420 | case NAMEPOLICY_PATH: | |||
421 | new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH"); | |||
422 | break; | |||
423 | case NAMEPOLICY_MAC: | |||
424 | new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC"); | |||
425 | break; | |||
426 | default: | |||
427 | break; | |||
428 | } | |||
429 | } | |||
430 | } | |||
431 | ||||
432 | if (should_rename(device, respect_predictable)) { | |||
433 | /* if not set by policy, fall back manually set name */ | |||
434 | if (!new_name) | |||
435 | new_name = config->name; | |||
436 | } else | |||
437 | new_name = NULL((void*)0); | |||
438 | ||||
439 | switch (config->mac_policy) { | |||
440 | case MACPOLICY_PERSISTENT: | |||
441 | if (mac_is_random(device)) { | |||
442 | r = get_mac(device, false0, &generated_mac); | |||
443 | if (r == -ENOENT2) { | |||
444 | log_warning_errno(r, "Could not generate persistent MAC address for %s: %m", old_name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 444, __func__, "Could not generate persistent MAC address for %s: %m" , old_name) : -abs(_e); }); | |||
445 | break; | |||
446 | } else if (r < 0) | |||
447 | return r; | |||
448 | mac = &generated_mac; | |||
449 | } | |||
450 | break; | |||
451 | case MACPOLICY_RANDOM: | |||
452 | if (!mac_is_random(device)) { | |||
453 | r = get_mac(device, true1, &generated_mac); | |||
454 | if (r == -ENOENT2) { | |||
455 | log_warning_errno(r, "Could not generate random MAC address for %s: %m", old_name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 455, __func__, "Could not generate random MAC address for %s: %m" , old_name) : -abs(_e); }); | |||
456 | break; | |||
457 | } else if (r < 0) | |||
458 | return r; | |||
459 | mac = &generated_mac; | |||
460 | } | |||
461 | break; | |||
462 | case MACPOLICY_NONE: | |||
463 | default: | |||
464 | mac = config->mac; | |||
465 | } | |||
466 | ||||
467 | r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu); | |||
468 | if (r < 0) | |||
469 | return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= ((_level) & 0x07) ) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/udev/net/link-config.c", 469, __func__, "Could not set Alias=, MACAddress= or MTU= on %s: %m" , old_name) : -abs(_e); }); | |||
470 | ||||
471 | *name = new_name; | |||
472 | ||||
473 | return 0; | |||
474 | } | |||
475 | ||||
476 | int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) { | |||
477 | const char *name; | |||
478 | char *driver = NULL((void*)0); | |||
479 | int r; | |||
480 | ||||
481 | name = udev_device_get_sysname(device); | |||
482 | if (!name) | |||
483 | return -EINVAL22; | |||
484 | ||||
485 | r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver); | |||
486 | if (r < 0) | |||
487 | return r; | |||
488 | ||||
489 | *ret = driver; | |||
490 | return 0; | |||
491 | } | |||
492 | ||||
493 | static const char* const mac_policy_table[_MACPOLICY_MAX] = { | |||
494 | [MACPOLICY_PERSISTENT] = "persistent", | |||
495 | [MACPOLICY_RANDOM] = "random", | |||
496 | [MACPOLICY_NONE] = "none" | |||
497 | }; | |||
498 | ||||
499 | DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy)const char *mac_policy_to_string(MACPolicy i) { if (i < 0 || i >= (MACPolicy) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(mac_policy_table), typeof(&*(mac_policy_table))), sizeof(mac_policy_table)/sizeof((mac_policy_table)[0]), ((void )0)))) return ((void*)0); return mac_policy_table[i]; } MACPolicy mac_policy_from_string(const char *s) { return (MACPolicy) string_table_lookup (mac_policy_table, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(mac_policy_table), typeof(&*(mac_policy_table))), sizeof(mac_policy_table)/sizeof((mac_policy_table)[0]), ((void )0))), s); }; | |||
500 | DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,int config_parse_mac_policy(const char *unit, const char *filename , unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { MACPolicy *i = data, x; do { if ((__builtin_expect (!!(!(filename)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("filename"), "../src/udev/net/link-config.c", 501, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("lvalue"), "../src/udev/net/link-config.c" , 501, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ( "rvalue"), "../src/udev/net/link-config.c", 501, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("data"), "../src/udev/net/link-config.c", 501 , __PRETTY_FUNCTION__); } while (0); x = mac_policy_from_string (rvalue); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_UDEV) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/udev/net/link-config.c" , 501, __func__, "Failed to parse MAC address policy" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; } | |||
501 | "Failed to parse MAC address policy")int config_parse_mac_policy(const char *unit, const char *filename , unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { MACPolicy *i = data, x; do { if ((__builtin_expect (!!(!(filename)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("filename"), "../src/udev/net/link-config.c", 501, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("lvalue"), "../src/udev/net/link-config.c" , 501, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ( "rvalue"), "../src/udev/net/link-config.c", 501, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("data"), "../src/udev/net/link-config.c", 501 , __PRETTY_FUNCTION__); } while (0); x = mac_policy_from_string (rvalue); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_UDEV) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/udev/net/link-config.c" , 501, __func__, "Failed to parse MAC address policy" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; }; | |||
502 | ||||
503 | static const char* const name_policy_table[_NAMEPOLICY_MAX] = { | |||
504 | [NAMEPOLICY_KERNEL] = "kernel", | |||
505 | [NAMEPOLICY_DATABASE] = "database", | |||
506 | [NAMEPOLICY_ONBOARD] = "onboard", | |||
507 | [NAMEPOLICY_SLOT] = "slot", | |||
508 | [NAMEPOLICY_PATH] = "path", | |||
509 | [NAMEPOLICY_MAC] = "mac" | |||
510 | }; | |||
511 | ||||
512 | DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy)const char *name_policy_to_string(NamePolicy i) { if (i < 0 || i >= (NamePolicy) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(name_policy_table), typeof (&*(name_policy_table))), sizeof(name_policy_table)/sizeof ((name_policy_table)[0]), ((void)0)))) return ((void*)0); return name_policy_table[i]; } NamePolicy name_policy_from_string(const char *s) { return (NamePolicy) string_table_lookup(name_policy_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(name_policy_table), typeof(&*(name_policy_table)) ), sizeof(name_policy_table)/sizeof((name_policy_table)[0]), ( (void)0))), s); }; | |||
513 | DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,int config_parse_name_policy(const char *unit, const char *filename , unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { NamePolicy **enums = data, x, *ys; __attribute__ ((cleanup(freep))) NamePolicy *xs = ((void*)0); const char *word , *state; size_t l, i = 0; do { if ((__builtin_expect(!!(!(filename )),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("filename"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("lvalue"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ( "rvalue"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("data"), "../src/udev/net/link-config.c", 515 , __PRETTY_FUNCTION__); } while (0); xs = ((NamePolicy*) calloc ((1), sizeof(NamePolicy))); if (!xs) return -12; *xs = _NAMEPOLICY_INVALID ; for ((state) = (rvalue), (word) = split(&(state), & (l), (" \t\n\r"), (0)); (word); (word) = split(&(state), & (l), (" \t\n\r"), (0))) { __attribute__((cleanup(freep))) char *en = ((void*)0); NamePolicy *new_xs; en = strndup(word, l); if (!en) return -12; if ((x = name_policy_from_string(en)) < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_UDEV) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/udev/net/link-config.c" , 515, __func__, "Failed to parse interface name policy" ", ignoring: %s" , en) : -abs(_e); }); continue; } for (ys = xs; x != _NAMEPOLICY_INVALID && *ys != _NAMEPOLICY_INVALID; ys++) { if (*ys == x) { ({ int _level = (5), _e = (0); (log_get_max_level_realm(LOG_REALM_UDEV ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/udev/net/link-config.c", 515, __func__ , "Duplicate entry, ignoring: %s", en) : -abs(_e); }); x = _NAMEPOLICY_INVALID ; } } if (x == _NAMEPOLICY_INVALID) continue; *(xs + i) = x; new_xs = realloc(xs, (++i + 1) * sizeof(NamePolicy)); if (new_xs) xs = new_xs; else return -12; *(xs + i) = _NAMEPOLICY_INVALID; } ({ free(*enums); (*enums) = (xs); (xs) = ((void*)0); 0; }); return 0; } | |||
| ||||
| ||||
514 | _NAMEPOLICY_INVALID,int config_parse_name_policy(const char *unit, const char *filename , unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { NamePolicy **enums = data, x, *ys; __attribute__ ((cleanup(freep))) NamePolicy *xs = ((void*)0); const char *word , *state; size_t l, i = 0; do { if ((__builtin_expect(!!(!(filename )),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("filename"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("lvalue"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ( "rvalue"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("data"), "../src/udev/net/link-config.c", 515 , __PRETTY_FUNCTION__); } while (0); xs = ((NamePolicy*) calloc ((1), sizeof(NamePolicy))); if (!xs) return -12; *xs = _NAMEPOLICY_INVALID ; for ((state) = (rvalue), (word) = split(&(state), & (l), (" \t\n\r"), (0)); (word); (word) = split(&(state), & (l), (" \t\n\r"), (0))) { __attribute__((cleanup(freep))) char *en = ((void*)0); NamePolicy *new_xs; en = strndup(word, l); if (!en) return -12; if ((x = name_policy_from_string(en)) < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_UDEV) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/udev/net/link-config.c" , 515, __func__, "Failed to parse interface name policy" ", ignoring: %s" , en) : -abs(_e); }); continue; } for (ys = xs; x != _NAMEPOLICY_INVALID && *ys != _NAMEPOLICY_INVALID; ys++) { if (*ys == x) { ({ int _level = (5), _e = (0); (log_get_max_level_realm(LOG_REALM_UDEV ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/udev/net/link-config.c", 515, __func__ , "Duplicate entry, ignoring: %s", en) : -abs(_e); }); x = _NAMEPOLICY_INVALID ; } } if (x == _NAMEPOLICY_INVALID) continue; *(xs + i) = x; new_xs = realloc(xs, (++i + 1) * sizeof(NamePolicy)); if (new_xs) xs = new_xs; else return -12; *(xs + i) = _NAMEPOLICY_INVALID; } ({ free(*enums); (*enums) = (xs); (xs) = ((void*)0); 0; }); return 0; } | |||
515 | "Failed to parse interface name policy")int config_parse_name_policy(const char *unit, const char *filename , unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { NamePolicy **enums = data, x, *ys; __attribute__ ((cleanup(freep))) NamePolicy *xs = ((void*)0); const char *word , *state; size_t l, i = 0; do { if ((__builtin_expect(!!(!(filename )),0))) log_assert_failed_realm(LOG_REALM_UDEV, ("filename"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("lvalue"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_UDEV, ( "rvalue"), "../src/udev/net/link-config.c", 515, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_UDEV, ("data"), "../src/udev/net/link-config.c", 515 , __PRETTY_FUNCTION__); } while (0); xs = ((NamePolicy*) calloc ((1), sizeof(NamePolicy))); if (!xs) return -12; *xs = _NAMEPOLICY_INVALID ; for ((state) = (rvalue), (word) = split(&(state), & (l), (" \t\n\r"), (0)); (word); (word) = split(&(state), & (l), (" \t\n\r"), (0))) { __attribute__((cleanup(freep))) char *en = ((void*)0); NamePolicy *new_xs; en = strndup(word, l); if (!en) return -12; if ((x = name_policy_from_string(en)) < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_UDEV) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/udev/net/link-config.c" , 515, __func__, "Failed to parse interface name policy" ", ignoring: %s" , en) : -abs(_e); }); continue; } for (ys = xs; x != _NAMEPOLICY_INVALID && *ys != _NAMEPOLICY_INVALID; ys++) { if (*ys == x) { ({ int _level = (5), _e = (0); (log_get_max_level_realm(LOG_REALM_UDEV ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/udev/net/link-config.c", 515, __func__ , "Duplicate entry, ignoring: %s", en) : -abs(_e); }); x = _NAMEPOLICY_INVALID ; } } if (x == _NAMEPOLICY_INVALID) continue; *(xs + i) = x; new_xs = realloc(xs, (++i + 1) * sizeof(NamePolicy)); if (new_xs) xs = new_xs; else return -12; *(xs + i) = _NAMEPOLICY_INVALID; } ({ free(*enums); (*enums) = (xs); (xs) = ((void*)0); 0; }); return 0; }; |