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