chiark / gitweb /
dc218eb79cb31ab4c21fb883c2f75d819252d893
[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->name);
100                 free(link->match_path);
101                 free(link->match_driver);
102                 free(link->match_type);
103                 free(link->description);
104                 free(link->alias);
105                 free(link->name_policy);
106
107                 free(link);
108         }
109 }
110
111 void link_config_ctx_free(link_config_ctx *ctx) {
112         if (!ctx)
113                 return;
114
115         safe_close(ctx->ethtool_fd);
116
117         sd_rtnl_unref(ctx->rtnl);
118
119         link_configs_free(ctx);
120
121         free(ctx);
122
123         return;
124 }
125
126 static int load_link(link_config_ctx *ctx, const char *filename) {
127         _cleanup_free_ link_config *link = NULL;
128         _cleanup_fclose_ FILE *file = NULL;
129         int r;
130
131         assert(ctx);
132         assert(filename);
133
134         file = fopen(filename, "re");
135         if (!file) {
136                 if (errno == ENOENT)
137                         return 0;
138                 else
139                         return -errno;
140         }
141
142         if (null_or_empty_fd(fileno(file))) {
143                 log_debug("Skipping empty file: %s", filename);
144                 return 0;
145         }
146
147         link = new0(link_config, 1);
148         if (!link)
149                 return log_oom();
150
151         link->mac_policy = _MACPOLICY_INVALID;
152         link->wol = _WOL_INVALID;
153         link->duplex = _DUP_INVALID;
154
155         r = config_parse(NULL, filename, file,
156                          "Match\0Link\0Ethernet\0",
157                          config_item_perf_lookup, link_config_gperf_lookup,
158                          false, false, true, link);
159         if (r < 0)
160                 return r;
161         else
162                 log_debug("Parsed configuration file %s", filename);
163
164         link->filename = strdup(filename);
165
166         LIST_PREPEND(links, ctx->links, link);
167         link = NULL;
168
169         return 0;
170 }
171
172 static bool enable_name_policy(void) {
173         _cleanup_free_ char *line = NULL;
174         const char *word, *state;
175         int r;
176         size_t l;
177
178         r = proc_cmdline(&line);
179         if (r < 0) {
180                 log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
181                 return true;
182         }
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 command line, 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                 return log_error_errno(r, "failed to enumerate link files: %m");
209
210         STRV_FOREACH_BACKWARDS(f, files) {
211                 r = load_link(ctx, *f);
212                 if (r < 0)
213                         return r;
214         }
215
216         return 0;
217 }
218
219 bool link_config_should_reload(link_config_ctx *ctx) {
220         return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
221 }
222
223 int link_config_get(link_config_ctx *ctx, struct udev_device *device,
224                     link_config **ret) {
225         link_config *link;
226
227         LIST_FOREACH(links, link, ctx->links) {
228                 const char* attr_value;
229                 unsigned char name_assign_type = NET_NAME_UNKNOWN;
230
231                 attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
232                 if (attr_value)
233                         (void)safe_atou8(attr_value, &name_assign_type);
234
235                 attr_value = udev_device_get_sysattr_value(device, "address");
236
237                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
238                                      link->match_type, link->match_name, link->match_host,
239                                      link->match_virt, link->match_kernel, link->match_arch,
240                                      attr_value ? ether_aton(attr_value) : NULL,
241                                      udev_device_get_property_value(device, "ID_PATH"),
242                                      udev_device_get_driver(udev_device_get_parent(device)),
243                                      udev_device_get_property_value(device, "ID_NET_DRIVER"),
244                                      udev_device_get_devtype(device),
245                                      udev_device_get_sysname(device),
246                                      name_assign_type == NET_NAME_RENAMED)) {
247                         log_debug("Config file %s applies to device %s",
248                                   link->filename,
249                                   udev_device_get_sysname(device));
250                         *ret = link;
251                         return 0;
252                 }
253         }
254
255         *ret = NULL;
256
257         return -ENOENT;
258 }
259
260 static bool mac_is_random(struct udev_device *device) {
261         const char *s;
262         unsigned type;
263         int r;
264
265         /* if we can't get the assign type, assume it is not random */
266         s = udev_device_get_sysattr_value(device, "addr_assign_type");
267         if (!s)
268                 return false;
269
270         r = safe_atou(s, &type);
271         if (r < 0)
272                 return false;
273
274         return type == NET_ADDR_RANDOM;
275 }
276
277 static bool should_rename(struct udev_device *device, bool respect_predictable) {
278         const char *s;
279         unsigned type;
280         int r;
281
282         /* if we can't get the assgin type, assume we should rename */
283         s = udev_device_get_sysattr_value(device, "name_assign_type");
284         if (!s)
285                 return true;
286
287         r = safe_atou(s, &type);
288         if (r < 0)
289                 return true;
290
291         switch (type) {
292         case NET_NAME_USER:
293         case NET_NAME_RENAMED:
294                 /* these were already named by userspace, do not touch again */
295                 return false;
296         case NET_NAME_PREDICTABLE:
297                 /* the kernel claims to have given a predictable name */
298                 if (respect_predictable)
299                         return false;
300                 /* fall through */
301         case NET_NAME_ENUM:
302         default:
303                 /* the name is known to be bad, or of an unknown type */
304                 return true;
305         }
306 }
307
308 static int get_mac(struct udev_device *device, bool want_random,
309                    struct ether_addr *mac) {
310         int r;
311
312         if (want_random)
313                 random_bytes(mac->ether_addr_octet, ETH_ALEN);
314         else {
315                 uint8_t result[8];
316
317                 r = net_get_unique_predictable_data(device, result);
318                 if (r < 0)
319                         return r;
320
321                 assert_cc(ETH_ALEN <= sizeof(result));
322                 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
323         }
324
325         /* see eth_random_addr in the kernel */
326         mac->ether_addr_octet[0] &= 0xfe;  /* clear multicast bit */
327         mac->ether_addr_octet[0] |= 0x02;  /* set local assignment bit (IEEE802) */
328
329         return 0;
330 }
331
332 int link_config_apply(link_config_ctx *ctx, link_config *config,
333                       struct udev_device *device, const char **name) {
334         const char *old_name;
335         const char *new_name = NULL;
336         struct ether_addr generated_mac;
337         struct ether_addr *mac = NULL;
338         bool respect_predictable = false;
339         int r, ifindex;
340
341         assert(ctx);
342         assert(config);
343         assert(device);
344         assert(name);
345
346         old_name = udev_device_get_sysname(device);
347         if (!old_name)
348                 return -EINVAL;
349
350         r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024,
351                               config->duplex);
352         if (r < 0)
353                 log_warning_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
354                                   old_name, config->speed / 1024,
355                                   duplex_to_string(config->duplex));
356
357         r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
358         if (r < 0)
359                 log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
360                                   old_name, wol_to_string(config->wol));
361
362         ifindex = udev_device_get_ifindex(device);
363         if (ifindex <= 0) {
364                 log_warning("Could not find ifindex");
365                 return -ENODEV;
366         }
367
368         if (ctx->enable_name_policy && config->name_policy) {
369                 NamePolicy *policy;
370
371                 for (policy = config->name_policy;
372                      !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
373                         switch (*policy) {
374                                 case NAMEPOLICY_KERNEL:
375                                         respect_predictable = true;
376                                         break;
377                                 case NAMEPOLICY_DATABASE:
378                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
379                                         break;
380                                 case NAMEPOLICY_ONBOARD:
381                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
382                                         break;
383                                 case NAMEPOLICY_SLOT:
384                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
385                                         break;
386                                 case NAMEPOLICY_PATH:
387                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
388                                         break;
389                                 case NAMEPOLICY_MAC:
390                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
391                                         break;
392                                 default:
393                                         break;
394                         }
395                 }
396         }
397
398         if (should_rename(device, respect_predictable)) {
399                 /* if not set by policy, fall back manually set name */
400                 if (!new_name)
401                         new_name = config->name;
402         } else
403                 new_name = NULL;
404
405         switch (config->mac_policy) {
406                 case MACPOLICY_PERSISTENT:
407                         if (mac_is_random(device)) {
408                                 r = get_mac(device, false, &generated_mac);
409                                 if (r == -ENOENT)
410                                         break;
411                                 else if (r < 0)
412                                         return r;
413                                 mac = &generated_mac;
414                         }
415                         break;
416                 case MACPOLICY_RANDOM:
417                         if (!mac_is_random(device)) {
418                                 r = get_mac(device, true, &generated_mac);
419                                 if (r == -ENOENT)
420                                         break;
421                                 else if (r < 0)
422                                         return r;
423                                 mac = &generated_mac;
424                         }
425                         break;
426                 default:
427                         mac = config->mac;
428         }
429
430         r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac,
431                                      config->mtu);
432         if (r < 0)
433                 return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
434
435         *name = new_name;
436
437         return 0;
438 }
439
440 int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
441         const char *name;
442         char *driver;
443         int r;
444
445         name = udev_device_get_sysname(device);
446         if (!name)
447                 return -EINVAL;
448
449         r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
450         if (r < 0)
451                 return r;
452
453         *ret = driver;
454         return 0;
455 }
456
457 static const char* const mac_policy_table[_MACPOLICY_MAX] = {
458         [MACPOLICY_PERSISTENT] = "persistent",
459         [MACPOLICY_RANDOM] = "random"
460 };
461
462 DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
463 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
464                          "Failed to parse MAC address policy");
465
466 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
467         [NAMEPOLICY_KERNEL] = "kernel",
468         [NAMEPOLICY_DATABASE] = "database",
469         [NAMEPOLICY_ONBOARD] = "onboard",
470         [NAMEPOLICY_SLOT] = "slot",
471         [NAMEPOLICY_PATH] = "path",
472         [NAMEPOLICY_MAC] = "mac"
473 };
474
475 DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
476 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
477                           _NAMEPOLICY_INVALID,
478                           "Failed to parse interface name policy");