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