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