Line data Source code
1 : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2 :
3 : /***
4 : This file is part of systemd.
5 :
6 : Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7 :
8 : systemd is free software; you can redistribute it and/or modify it
9 : under the terms of the GNU Lesser General Public License as published by
10 : the Free Software Foundation; either version 2.1 of the License, or
11 : (at your option) any later version.
12 :
13 : systemd is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 : ***/
21 :
22 : #include <netinet/ether.h>
23 : #include <linux/netdevice.h>
24 :
25 :
26 : #include "missing.h"
27 : #include "link-config.h"
28 : #include "ethtool-util.h"
29 :
30 : #include "libudev-private.h"
31 : #include "sd-netlink.h"
32 : #include "util.h"
33 : #include "log.h"
34 : #include "strv.h"
35 : #include "path-util.h"
36 : #include "conf-parser.h"
37 : #include "conf-files.h"
38 : #include "netlink-util.h"
39 : #include "network-internal.h"
40 : #include "random-util.h"
41 :
42 : struct link_config_ctx {
43 : LIST_HEAD(link_config, links);
44 :
45 : int ethtool_fd;
46 :
47 : bool enable_name_policy;
48 :
49 : sd_netlink *rtnl;
50 :
51 : usec_t link_dirs_ts_usec;
52 : };
53 :
54 : static const char* const link_dirs[] = {
55 : "/etc/systemd/network",
56 : "/run/systemd/network",
57 : "/usr/lib/systemd/network",
58 : #ifdef HAVE_SPLIT_USR
59 : "/lib/systemd/network",
60 : #endif
61 : NULL};
62 :
63 0 : static void link_config_free(link_config *link) {
64 0 : if (!link)
65 0 : return;
66 :
67 0 : free(link->filename);
68 :
69 0 : free(link->match_mac);
70 0 : strv_free(link->match_path);
71 0 : strv_free(link->match_driver);
72 0 : strv_free(link->match_type);
73 0 : free(link->match_name);
74 0 : free(link->match_host);
75 0 : free(link->match_virt);
76 0 : free(link->match_kernel);
77 0 : free(link->match_arch);
78 :
79 0 : free(link->description);
80 0 : free(link->mac);
81 0 : free(link->name_policy);
82 0 : free(link->name);
83 0 : free(link->alias);
84 :
85 0 : free(link);
86 : }
87 :
88 0 : DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
89 :
90 0 : static void link_configs_free(link_config_ctx *ctx) {
91 : link_config *link, *link_next;
92 :
93 0 : if (!ctx)
94 0 : return;
95 :
96 0 : LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
97 0 : link_config_free(link);
98 : }
99 :
100 0 : void link_config_ctx_free(link_config_ctx *ctx) {
101 0 : if (!ctx)
102 0 : return;
103 :
104 0 : safe_close(ctx->ethtool_fd);
105 :
106 0 : sd_netlink_unref(ctx->rtnl);
107 :
108 0 : link_configs_free(ctx);
109 :
110 0 : free(ctx);
111 :
112 0 : return;
113 : }
114 :
115 0 : DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
116 :
117 0 : int link_config_ctx_new(link_config_ctx **ret) {
118 0 : _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
119 :
120 0 : if (!ret)
121 0 : return -EINVAL;
122 :
123 0 : ctx = new0(link_config_ctx, 1);
124 0 : if (!ctx)
125 0 : return -ENOMEM;
126 :
127 0 : LIST_HEAD_INIT(ctx->links);
128 :
129 0 : ctx->ethtool_fd = -1;
130 :
131 0 : ctx->enable_name_policy = true;
132 :
133 0 : *ret = ctx;
134 0 : ctx = NULL;
135 :
136 0 : return 0;
137 : }
138 :
139 0 : static int load_link(link_config_ctx *ctx, const char *filename) {
140 0 : _cleanup_(link_config_freep) link_config *link = NULL;
141 0 : _cleanup_fclose_ FILE *file = NULL;
142 : int r;
143 :
144 0 : assert(ctx);
145 0 : assert(filename);
146 :
147 0 : file = fopen(filename, "re");
148 0 : if (!file) {
149 0 : if (errno == ENOENT)
150 0 : return 0;
151 : else
152 0 : return -errno;
153 : }
154 :
155 0 : if (null_or_empty_fd(fileno(file))) {
156 0 : log_debug("Skipping empty file: %s", filename);
157 0 : return 0;
158 : }
159 :
160 0 : link = new0(link_config, 1);
161 0 : if (!link)
162 0 : return log_oom();
163 :
164 0 : link->mac_policy = _MACPOLICY_INVALID;
165 0 : link->wol = _WOL_INVALID;
166 0 : link->duplex = _DUP_INVALID;
167 :
168 0 : r = config_parse(NULL, filename, file,
169 : "Match\0Link\0Ethernet\0",
170 : config_item_perf_lookup, link_config_gperf_lookup,
171 : false, false, true, link);
172 0 : if (r < 0)
173 0 : return r;
174 : else
175 0 : log_debug("Parsed configuration file %s", filename);
176 :
177 0 : if (link->mtu > UINT_MAX || link->speed > UINT_MAX)
178 0 : return -ERANGE;
179 :
180 0 : link->filename = strdup(filename);
181 :
182 0 : LIST_PREPEND(links, ctx->links, link);
183 0 : link = NULL;
184 :
185 0 : return 0;
186 : }
187 :
188 0 : static bool enable_name_policy(void) {
189 0 : _cleanup_free_ char *line = NULL;
190 : const char *word, *state;
191 : int r;
192 : size_t l;
193 :
194 0 : r = proc_cmdline(&line);
195 0 : if (r < 0) {
196 0 : log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
197 0 : return true;
198 : }
199 :
200 0 : FOREACH_WORD_QUOTED(word, l, line, state)
201 0 : if (strneq(word, "net.ifnames=0", l))
202 0 : return false;
203 :
204 0 : return true;
205 : }
206 :
207 0 : int link_config_load(link_config_ctx *ctx) {
208 : int r;
209 0 : _cleanup_strv_free_ char **files;
210 : char **f;
211 :
212 0 : link_configs_free(ctx);
213 :
214 0 : if (!enable_name_policy()) {
215 0 : ctx->enable_name_policy = false;
216 0 : log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
217 : }
218 :
219 : /* update timestamp */
220 0 : paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
221 :
222 0 : r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
223 0 : if (r < 0)
224 0 : return log_error_errno(r, "failed to enumerate link files: %m");
225 :
226 0 : STRV_FOREACH_BACKWARDS(f, files) {
227 0 : r = load_link(ctx, *f);
228 0 : if (r < 0)
229 0 : return r;
230 : }
231 :
232 0 : return 0;
233 : }
234 :
235 0 : bool link_config_should_reload(link_config_ctx *ctx) {
236 0 : return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
237 : }
238 :
239 0 : int link_config_get(link_config_ctx *ctx, struct udev_device *device,
240 : link_config **ret) {
241 : link_config *link;
242 :
243 0 : assert(ctx);
244 0 : assert(device);
245 0 : assert(ret);
246 :
247 0 : LIST_FOREACH(links, link, ctx->links) {
248 : const char* attr_value;
249 :
250 0 : attr_value = udev_device_get_sysattr_value(device, "address");
251 :
252 0 : if (net_match_config(link->match_mac, link->match_path, link->match_driver,
253 0 : link->match_type, link->match_name, link->match_host,
254 : link->match_virt, link->match_kernel, link->match_arch,
255 : attr_value ? ether_aton(attr_value) : NULL,
256 : udev_device_get_property_value(device, "ID_PATH"),
257 : udev_device_get_driver(udev_device_get_parent(device)),
258 : udev_device_get_property_value(device, "ID_NET_DRIVER"),
259 : udev_device_get_devtype(device),
260 : udev_device_get_sysname(device))) {
261 0 : if (link->match_name) {
262 0 : unsigned char name_assign_type = NET_NAME_UNKNOWN;
263 :
264 0 : attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
265 0 : if (attr_value)
266 0 : (void) safe_atou8(attr_value, &name_assign_type);
267 :
268 0 : if (name_assign_type == NET_NAME_ENUM) {
269 0 : log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
270 : link->filename, udev_device_get_sysname(device));
271 0 : *ret = link;
272 :
273 0 : return 0;
274 0 : } else if (name_assign_type == NET_NAME_RENAMED) {
275 0 : log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
276 : link->filename, udev_device_get_sysname(device));
277 :
278 0 : continue;
279 : }
280 : }
281 :
282 0 : log_debug("Config file %s applies to device %s",
283 : link->filename, udev_device_get_sysname(device));
284 :
285 0 : *ret = link;
286 :
287 0 : return 0;
288 : }
289 : }
290 :
291 0 : *ret = NULL;
292 :
293 0 : return -ENOENT;
294 : }
295 :
296 0 : static bool mac_is_random(struct udev_device *device) {
297 : const char *s;
298 : unsigned type;
299 : int r;
300 :
301 : /* if we can't get the assign type, assume it is not random */
302 0 : s = udev_device_get_sysattr_value(device, "addr_assign_type");
303 0 : if (!s)
304 0 : return false;
305 :
306 0 : r = safe_atou(s, &type);
307 0 : if (r < 0)
308 0 : return false;
309 :
310 0 : return type == NET_ADDR_RANDOM;
311 : }
312 :
313 0 : static bool should_rename(struct udev_device *device, bool respect_predictable) {
314 : const char *s;
315 : unsigned type;
316 : int r;
317 :
318 : /* if we can't get the assgin type, assume we should rename */
319 0 : s = udev_device_get_sysattr_value(device, "name_assign_type");
320 0 : if (!s)
321 0 : return true;
322 :
323 0 : r = safe_atou(s, &type);
324 0 : if (r < 0)
325 0 : return true;
326 :
327 0 : switch (type) {
328 : case NET_NAME_USER:
329 : case NET_NAME_RENAMED:
330 : /* these were already named by userspace, do not touch again */
331 0 : return false;
332 : case NET_NAME_PREDICTABLE:
333 : /* the kernel claims to have given a predictable name */
334 0 : if (respect_predictable)
335 0 : return false;
336 : /* fall through */
337 : case NET_NAME_ENUM:
338 : default:
339 : /* the name is known to be bad, or of an unknown type */
340 0 : return true;
341 : }
342 : }
343 :
344 0 : static int get_mac(struct udev_device *device, bool want_random,
345 : struct ether_addr *mac) {
346 : int r;
347 :
348 0 : if (want_random)
349 0 : random_bytes(mac->ether_addr_octet, ETH_ALEN);
350 : else {
351 : uint8_t result[8];
352 :
353 0 : r = net_get_unique_predictable_data(device, result);
354 0 : if (r < 0)
355 0 : return r;
356 :
357 : assert_cc(ETH_ALEN <= sizeof(result));
358 0 : memcpy(mac->ether_addr_octet, result, ETH_ALEN);
359 : }
360 :
361 : /* see eth_random_addr in the kernel */
362 0 : mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
363 0 : mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
364 :
365 0 : return 0;
366 : }
367 :
368 0 : int link_config_apply(link_config_ctx *ctx, link_config *config,
369 : struct udev_device *device, const char **name) {
370 : const char *old_name;
371 0 : const char *new_name = NULL;
372 : struct ether_addr generated_mac;
373 0 : struct ether_addr *mac = NULL;
374 0 : bool respect_predictable = false;
375 : int r, ifindex;
376 :
377 0 : assert(ctx);
378 0 : assert(config);
379 0 : assert(device);
380 0 : assert(name);
381 :
382 0 : old_name = udev_device_get_sysname(device);
383 0 : if (!old_name)
384 0 : return -EINVAL;
385 :
386 0 : r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
387 0 : if (r < 0)
388 0 : log_warning_errno(r, "Could not set speed or duplex of %s to %zu Mbps (%s): %m",
389 : old_name, config->speed / 1024,
390 : duplex_to_string(config->duplex));
391 :
392 0 : r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
393 0 : if (r < 0)
394 0 : log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
395 : old_name, wol_to_string(config->wol));
396 :
397 0 : ifindex = udev_device_get_ifindex(device);
398 0 : if (ifindex <= 0) {
399 0 : log_warning("Could not find ifindex");
400 0 : return -ENODEV;
401 : }
402 :
403 0 : if (ctx->enable_name_policy && config->name_policy) {
404 : NamePolicy *policy;
405 :
406 0 : for (policy = config->name_policy;
407 0 : !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
408 0 : switch (*policy) {
409 : case NAMEPOLICY_KERNEL:
410 0 : respect_predictable = true;
411 0 : break;
412 : case NAMEPOLICY_DATABASE:
413 0 : new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
414 0 : break;
415 : case NAMEPOLICY_ONBOARD:
416 0 : new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
417 0 : break;
418 : case NAMEPOLICY_SLOT:
419 0 : new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
420 0 : break;
421 : case NAMEPOLICY_PATH:
422 0 : new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
423 0 : break;
424 : case NAMEPOLICY_MAC:
425 0 : new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
426 0 : break;
427 : default:
428 0 : break;
429 : }
430 : }
431 : }
432 :
433 0 : if (should_rename(device, respect_predictable)) {
434 : /* if not set by policy, fall back manually set name */
435 0 : if (!new_name)
436 0 : new_name = config->name;
437 : } else
438 0 : new_name = NULL;
439 :
440 0 : switch (config->mac_policy) {
441 : case MACPOLICY_PERSISTENT:
442 0 : if (mac_is_random(device)) {
443 0 : r = get_mac(device, false, &generated_mac);
444 0 : if (r == -ENOENT) {
445 0 : log_warning_errno(r, "Could not generate persistent MAC address for %s: %m", old_name);
446 0 : break;
447 0 : } else if (r < 0)
448 0 : return r;
449 0 : mac = &generated_mac;
450 : }
451 0 : break;
452 : case MACPOLICY_RANDOM:
453 0 : if (!mac_is_random(device)) {
454 0 : r = get_mac(device, true, &generated_mac);
455 0 : if (r == -ENOENT) {
456 0 : log_warning_errno(r, "Could not generate random MAC address for %s: %m", old_name);
457 0 : break;
458 0 : } else if (r < 0)
459 0 : return r;
460 0 : mac = &generated_mac;
461 : }
462 0 : break;
463 : default:
464 0 : mac = config->mac;
465 : }
466 :
467 0 : r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu);
468 0 : if (r < 0)
469 0 : return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
470 :
471 0 : *name = new_name;
472 :
473 0 : return 0;
474 : }
475 :
476 0 : int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
477 : const char *name;
478 0 : char *driver = NULL;
479 : int r;
480 :
481 0 : name = udev_device_get_sysname(device);
482 0 : if (!name)
483 0 : return -EINVAL;
484 :
485 0 : r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
486 0 : if (r < 0)
487 0 : return r;
488 :
489 0 : *ret = driver;
490 0 : return 0;
491 : }
492 :
493 : static const char* const mac_policy_table[_MACPOLICY_MAX] = {
494 : [MACPOLICY_PERSISTENT] = "persistent",
495 : [MACPOLICY_RANDOM] = "random"
496 : };
497 :
498 8 : DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
499 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
500 : "Failed to parse MAC address policy");
501 :
502 : static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
503 : [NAMEPOLICY_KERNEL] = "kernel",
504 : [NAMEPOLICY_DATABASE] = "database",
505 : [NAMEPOLICY_ONBOARD] = "onboard",
506 : [NAMEPOLICY_SLOT] = "slot",
507 : [NAMEPOLICY_PATH] = "path",
508 : [NAMEPOLICY_MAC] = "mac"
509 : };
510 :
511 16 : DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
512 0 : DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
513 : _NAMEPOLICY_INVALID,
514 : "Failed to parse interface name policy");
|