chiark / gitweb /
log: log_error() and friends add a newline after each line anyway, so avoid including...
[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 "net-util.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         char **link_dirs;
54         usec_t link_dirs_ts_usec;
55 };
56
57 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
58 #define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
59
60 int link_config_ctx_new(link_config_ctx **ret) {
61         _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
62
63         if (!ret)
64                 return -EINVAL;
65
66         ctx = new0(link_config_ctx, 1);
67         if (!ctx)
68                 return -ENOMEM;
69
70         LIST_HEAD_INIT(ctx->links);
71
72         ctx->ethtool_fd = -1;
73
74         ctx->enable_name_policy = true;
75
76         ctx->link_dirs = strv_new("/etc/systemd/network",
77                                   "/run/systemd/network",
78                                   "/usr/lib/systemd/network",
79 #ifdef HAVE_SPLIT_USR
80                                   "/lib/systemd/network",
81 #endif
82                                   NULL);
83         if (!ctx->link_dirs) {
84                 log_error("failed to build link config directory array");
85                 return -ENOMEM;
86         }
87
88         if (!path_strv_canonicalize_uniq(ctx->link_dirs)) {
89                 log_error("failed to canonicalize link config directories");
90                 return -ENOMEM;
91         }
92
93         *ret = ctx;
94         ctx = NULL;
95
96         return 0;
97 }
98
99 static int link_config_ctx_connect(link_config_ctx *ctx) {
100         int r;
101
102         if (ctx->ethtool_fd >= 0 && ctx->rtnl)
103                 return 0;
104
105         r = ethtool_connect(&ctx->ethtool_fd);
106         if (r < 0)
107                 return r;
108
109         r = sd_rtnl_open(0, &ctx->rtnl);
110         if (r < 0)
111                 return r;
112
113         return 0;
114 }
115
116 static void link_configs_free(link_config_ctx *ctx) {
117         link_config *link, *link_next;
118
119         if (!ctx)
120                 return;
121
122         LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
123                 free(link->filename);
124                 free(link->match_path);
125                 free(link->match_driver);
126                 free(link->match_type);
127                 free(link->description);
128                 free(link->alias);
129
130                 free(link);
131         }
132 }
133
134 void link_config_ctx_free(link_config_ctx *ctx) {
135         if (!ctx)
136                 return;
137
138         if (ctx->ethtool_fd >= 0)
139                 close_nointr_nofail(ctx->ethtool_fd);
140
141         sd_rtnl_unref(ctx->rtnl);
142
143         strv_free(ctx->link_dirs);
144         link_configs_free(ctx);
145
146         free(ctx);
147
148         return;
149 }
150
151 static int load_link(link_config_ctx *ctx, const char *filename) {
152         link_config *link;
153         _cleanup_fclose_ FILE *file;
154         int r;
155
156         assert(ctx);
157         assert(filename);
158
159         file = fopen(filename, "re");
160         if (!file) {
161                 if (errno == ENOENT)
162                         return 0;
163                 else
164                         return errno;
165         }
166
167         link = new0(link_config, 1);
168         if (!link) {
169                 r = log_oom();
170                 goto failure;
171         }
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, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
178                          (void*) link_config_gperf_lookup, false, false, link);
179         if (r < 0) {
180                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
181                 goto failure;
182         } else
183                 log_debug("Parsed configuration file %s", filename);
184
185         link->filename = strdup(filename);
186
187         LIST_PREPEND(links, ctx->links, link);
188
189         return 0;
190
191 failure:
192         free(link);
193         return r;
194 }
195
196 static bool enable_name_policy(void) {
197         _cleanup_free_ char *line;
198         char *w, *state;
199         int r;
200         size_t l;
201
202         r = proc_cmdline(&line);
203         if (r < 0)
204                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
205         if (r <= 0)
206                 return true;
207
208         FOREACH_WORD_QUOTED(w, l, line, state)
209                 if (strneq(w, "net.ifnames=0", l))
210                         return false;
211
212         return true;
213 }
214
215 int link_config_load(link_config_ctx *ctx) {
216         int r;
217         char **files, **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(ctx->link_dirs, &ctx->link_dirs_ts_usec, true);
228
229         r = conf_files_list_strv(&files, ".link", NULL, (const char **)ctx->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(ctx->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,
254                                      link->match_driver, link->match_type, NULL,
255                                      udev_device_get_sysattr_value(device, "address"),
256                                      udev_device_get_property_value(device, "ID_PATH"),
257                                      udev_device_get_driver(device),
258                                      udev_device_get_devtype(device),
259                                      NULL)) {
260                         log_debug("Config file %s applies to device %s",
261                                   link->filename,
262                                   udev_device_get_sysname(device));
263                         *ret = link;
264                         return 0;
265                 }
266         }
267
268         *ret = NULL;
269
270         return -ENOENT;
271 }
272
273 static bool mac_is_random(struct udev_device *device) {
274         const char *s;
275         unsigned type;
276         int r;
277
278         s = udev_device_get_sysattr_value(device, "addr_assign_type");
279         if (!s)
280                 return false; /* if we don't know, assume it is not random */
281         r = safe_atou(s, &type);
282         if (r < 0)
283                 return false;
284
285         /* check for NET_ADDR_RANDOM */
286         return type == 1;
287 }
288
289 static bool mac_is_permanent(struct udev_device *device) {
290         const char *s;
291         unsigned type;
292         int r;
293
294         s = udev_device_get_sysattr_value(device, "addr_assign_type");
295         if (!s)
296                 return true; /* if we don't know, assume it is permanent */
297         r = safe_atou(s, &type);
298         if (r < 0)
299                 return true;
300
301         /* check for NET_ADDR_PERM */
302         return type == 0;
303 }
304
305 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
306
307 static int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
308         int r;
309
310         if (want_random)
311                 random_bytes(mac->ether_addr_octet, ETH_ALEN);
312         else {
313                 const char *name;
314                 uint8_t result[8];
315                 size_t l, sz;
316                 uint8_t *v;
317
318                 /* fetch some persistent data unique (on this machine) to this device */
319                 name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
320                 if (!name) {
321                         name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
322                         if (!name) {
323                                 name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
324                                 if (!name)
325                                         return -ENOENT;
326                         }
327                 }
328
329                 l = strlen(name);
330                 sz = sizeof(sd_id128_t) + l;
331                 v = alloca(sz);
332
333                 /* fetch some persistent data unique to this machine */
334                 r = sd_id128_get_machine((sd_id128_t*) v);
335                 if (r < 0)
336                         return r;
337                 memcpy(v + sizeof(sd_id128_t), name, l);
338
339                 /* Let's hash the machine ID plus the device name. We
340                  * use a fixed, but originally randomly created hash
341                  * key here. */
342                 siphash24(result, v, sz, HASH_KEY.bytes);
343
344                 assert_cc(ETH_ALEN <= sizeof(result));
345                 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
346         }
347
348         /* see eth_random_addr in the kernel */
349         mac->ether_addr_octet[0] &= 0xfe;        /* clear multicast bit */
350         mac->ether_addr_octet[0] |= 0x02;        /* set local assignment bit (IEEE802) */
351
352         return 0;
353 }
354
355 int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
356         const char *old_name;
357         const char *new_name = NULL;
358         struct ether_addr generated_mac;
359         struct ether_addr *mac = NULL;
360         int r, ifindex;
361
362         assert(ctx);
363         assert(config);
364         assert(device);
365         assert(name);
366
367         r = link_config_ctx_connect(ctx);
368         if (r < 0)
369                 return r;
370
371         old_name = udev_device_get_sysname(device);
372         if (!old_name)
373                 return -EINVAL;
374
375         r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed, config->duplex);
376         if (r < 0)
377                 log_warning("Could not set speed or duplex of %s to %u Mbytes (%s): %s",
378                              old_name, config->speed, duplex_to_string(config->duplex), strerror(-r));
379
380         r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
381         if (r < 0)
382                 log_warning("Could not set WakeOnLan of %s to %s: %s",
383                             old_name, wol_to_string(config->wol), strerror(-r));
384
385         ifindex = udev_device_get_ifindex(device);
386         if (ifindex <= 0) {
387                 log_warning("Could not find ifindex");
388                 return -ENODEV;
389         }
390
391         if (ctx->enable_name_policy && config->name_policy) {
392                 NamePolicy *policy;
393
394                 for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
395                         switch (*policy) {
396                                 case NAMEPOLICY_ONBOARD:
397                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
398                                         break;
399                                 case NAMEPOLICY_SLOT:
400                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
401                                         break;
402                                 case NAMEPOLICY_PATH:
403                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
404                                         break;
405                                 case NAMEPOLICY_MAC:
406                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
407                                         break;
408                                 default:
409                                         break;
410                         }
411                 }
412         }
413
414         if (new_name)
415                 *name = new_name; /* a name was set by a policy */
416         else if (config->name)
417                 *name = config->name; /* a name was set manually in the config */
418         else
419                 *name = NULL;
420
421         switch (config->mac_policy) {
422                 case MACPOLICY_PERSISTENT:
423                         if (!mac_is_permanent(device)) {
424                                 r = get_mac(device, false, &generated_mac);
425                                 if (r < 0)
426                                         return r;
427                                 mac = &generated_mac;
428                         }
429                         break;
430                 case MACPOLICY_RANDOM:
431                         if (!mac_is_random(device)) {
432                                 r = get_mac(device, true, &generated_mac);
433                                 if (r < 0)
434                                         return r;
435                                 mac = &generated_mac;
436                         }
437                         break;
438                 default:
439                         mac = config->mac;
440         }
441
442         r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
443         if (r < 0) {
444                 log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
445                 return r;
446         }
447
448         return 0;
449 }
450
451 static const char* const mac_policy_table[] = {
452         [MACPOLICY_PERSISTENT] = "persistent",
453         [MACPOLICY_RANDOM] = "random"
454 };
455
456 DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
457 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
458
459 static const char* const name_policy_table[] = {
460         [NAMEPOLICY_ONBOARD] = "onboard",
461         [NAMEPOLICY_SLOT] = "slot",
462         [NAMEPOLICY_PATH] = "path",
463         [NAMEPOLICY_MAC] = "mac"
464 };
465
466 DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
467 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");