Bug Summary

File:build-scan/../src/udev/net/link-config.c
Warning:line 513, column 1
Potential leak of memory pointed to by 'xs'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name link-config.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/udev/libudev-core.a.p -I src/udev -I ../src/udev -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I ../src/udev/net -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -D LOG_REALM=LOG_REALM_UDEV -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/udev/net/link-config.c
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
28struct 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
40static 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
49static 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
75DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free)static inline void link_config_freep(link_config* *p) { if (*
p) link_config_free(*p); }
;
76
77static 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
87void 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
102DEFINE_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
104int 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
125static 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
180static bool_Bool enable_name_policy(void) {
181 bool_Bool b;
182
183 return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
184}
185
186int 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
214bool_Bool link_config_should_reload(link_config_ctx *ctx) {
215 return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false0);
216}
217
218int 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
276static 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
293static 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
323static 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_14 { 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
347int 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_X15 = ((config
->speed)); const typeof((1000000)) __unique_prefix_Y16 = (
(1000000)); (__unique_prefix_X15 / __unique_prefix_Y16 + !!(__unique_prefix_X15
% __unique_prefix_Y16)); })
;
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
476int 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
493static const char* const mac_policy_table[_MACPOLICY_MAX] = {
494 [MACPOLICY_PERSISTENT] = "persistent",
495 [MACPOLICY_RANDOM] = "random",
496 [MACPOLICY_NONE] = "none"
497};
498
499DEFINE_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); }
;
500DEFINE_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
503static 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
512DEFINE_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); }
;
513DEFINE_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; }
1
Assuming 'filename' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
4
Assuming 'lvalue' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
7
Assuming 'rvalue' is non-null
8
Taking false branch
9
Loop condition is false. Exiting loop
10
Assuming 'data' is non-null
11
Taking false branch
12
Loop condition is false. Exiting loop
13
Assuming 'xs' is non-null
14
Taking false branch
15
Loop condition is true. Entering loop body
16
Assuming 'en' is non-null
17
Taking false branch
18
Assuming the condition is false
19
Taking false branch
20
Loop condition is false. Execution continues on line 513
21
Taking false branch
22
Memory is allocated
23
Assuming 'new_xs' is non-null
24
Taking true branch
25
Loop condition is true. Entering loop body
26
Assuming 'en' is null
27
Taking true branch
28
Potential leak of memory pointed to by 'xs'
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; }
;