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