chiark / gitweb /
Be more careful when checking for empty files
[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         file = fopen(filename, "re");
157         if (!file) {
158                 if (errno == ENOENT)
159                         return 0;
160                 else
161                         return -errno;
162         }
163
164         if (null_or_empty_fd(fileno(file))) {
165                 log_debug("Skipping empty file: %s", filename);
166                 return 0;
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, true, link);
181         if (r < 0)
182                 return r;
183         else
184                 log_debug("Parsed configuration file %s", filename);
185
186         link->filename = strdup(filename);
187
188         LIST_PREPEND(links, ctx->links, link);
189         link = NULL;
190
191         return 0;
192 }
193
194 static bool enable_name_policy(void) {
195         _cleanup_free_ char *line = NULL;
196         char *w, *state;
197         int r;
198         size_t l;
199
200         r = proc_cmdline(&line);
201         if (r < 0)
202                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
203         if (r <= 0)
204                 return true;
205
206         FOREACH_WORD_QUOTED(w, l, line, state)
207                 if (strneq(w, "net.ifnames=0", l))
208                         return false;
209
210         return true;
211 }
212
213 int link_config_load(link_config_ctx *ctx) {
214         int r;
215         _cleanup_strv_free_ char **files;
216         char **f;
217
218         link_configs_free(ctx);
219
220         if (!enable_name_policy()) {
221                 ctx->enable_name_policy = false;
222                 log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
223         }
224
225         /* update timestamp */
226         paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
227
228         r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
229         if (r < 0) {
230                 log_error("failed to enumerate link files: %s", strerror(-r));
231                 return r;
232         }
233
234         STRV_FOREACH_BACKWARDS(f, files) {
235                 r = load_link(ctx, *f);
236                 if (r < 0)
237                         return r;
238         }
239
240         return 0;
241 }
242
243 bool link_config_should_reload(link_config_ctx *ctx) {
244         return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
245 }
246
247 int link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
248         link_config *link;
249
250         LIST_FOREACH(links, link, ctx->links) {
251
252                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
253                                      link->match_type, NULL, link->match_host,
254                                      link->match_virt, link->match_kernel, link->match_arch,
255                                      ether_aton(udev_device_get_sysattr_value(device, "address")),
256                                      udev_device_get_property_value(device, "ID_PATH"),
257                                      udev_device_get_driver(udev_device_get_parent(device)),
258                                      udev_device_get_property_value(device, "ID_NET_DRIVER"),
259                                      udev_device_get_devtype(device),
260                                      NULL)) {
261                         log_debug("Config file %s applies to device %s",
262                                   link->filename,
263                                   udev_device_get_sysname(device));
264                         *ret = link;
265                         return 0;
266                 }
267         }
268
269         *ret = NULL;
270
271         return -ENOENT;
272 }
273
274 static bool mac_is_random(struct udev_device *device) {
275         const char *s;
276         unsigned type;
277         int r;
278
279         s = udev_device_get_sysattr_value(device, "addr_assign_type");
280         if (!s)
281                 return false; /* if we don't know, assume it is not random */
282         r = safe_atou(s, &type);
283         if (r < 0)
284                 return false;
285
286         /* check for NET_ADDR_RANDOM */
287         return type == 1;
288 }
289
290 static int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
291         int r;
292
293         if (want_random)
294                 random_bytes(mac->ether_addr_octet, ETH_ALEN);
295         else {
296                 uint8_t result[8];
297
298                 r = net_get_unique_predictable_data(device, result);
299                 if (r < 0)
300                         return r;
301
302                 assert_cc(ETH_ALEN <= sizeof(result));
303                 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
304         }
305
306         /* see eth_random_addr in the kernel */
307         mac->ether_addr_octet[0] &= 0xfe;        /* clear multicast bit */
308         mac->ether_addr_octet[0] |= 0x02;        /* set local assignment bit (IEEE802) */
309
310         return 0;
311 }
312
313 int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
314         const char *old_name;
315         const char *new_name = NULL;
316         struct ether_addr generated_mac;
317         struct ether_addr *mac = NULL;
318         int r, ifindex;
319
320         assert(ctx);
321         assert(config);
322         assert(device);
323         assert(name);
324
325         r = link_config_ctx_connect(ctx);
326         if (r < 0)
327                 return r;
328
329         old_name = udev_device_get_sysname(device);
330         if (!old_name)
331                 return -EINVAL;
332
333         r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
334         if (r < 0)
335                 log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
336                             old_name, config->speed / 1024, duplex_to_string(config->duplex),
337                             strerror(-r));
338
339         r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
340         if (r < 0)
341                 log_warning("Could not set WakeOnLan of %s to %s: %s",
342                             old_name, wol_to_string(config->wol), strerror(-r));
343
344         ifindex = udev_device_get_ifindex(device);
345         if (ifindex <= 0) {
346                 log_warning("Could not find ifindex");
347                 return -ENODEV;
348         }
349
350         if (ctx->enable_name_policy && config->name_policy) {
351                 NamePolicy *policy;
352
353                 for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
354                         switch (*policy) {
355                                 case NAMEPOLICY_DATABASE:
356                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
357                                         break;
358                                 case NAMEPOLICY_ONBOARD:
359                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
360                                         break;
361                                 case NAMEPOLICY_SLOT:
362                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
363                                         break;
364                                 case NAMEPOLICY_PATH:
365                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
366                                         break;
367                                 case NAMEPOLICY_MAC:
368                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
369                                         break;
370                                 default:
371                                         break;
372                         }
373                 }
374         }
375
376         if (new_name)
377                 *name = new_name; /* a name was set by a policy */
378         else if (config->name)
379                 *name = config->name; /* a name was set manually in the config */
380         else
381                 *name = NULL;
382
383         switch (config->mac_policy) {
384                 case MACPOLICY_PERSISTENT:
385                         if (mac_is_random(device)) {
386                                 r = get_mac(device, false, &generated_mac);
387                                 if (r == -ENOENT)
388                                         break;
389                                 else if (r < 0)
390                                         return r;
391                                 mac = &generated_mac;
392                         }
393                         break;
394                 case MACPOLICY_RANDOM:
395                         if (!mac_is_random(device)) {
396                                 r = get_mac(device, true, &generated_mac);
397                                 if (r == -ENOENT)
398                                         break;
399                                 else if (r < 0)
400                                         return r;
401                                 mac = &generated_mac;
402                         }
403                         break;
404                 default:
405                         mac = config->mac;
406         }
407
408         r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
409         if (r < 0) {
410                 log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
411                 return r;
412         }
413
414         return 0;
415 }
416
417 int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
418         const char *name;
419         char *driver;
420         int r;
421
422         r = link_config_ctx_connect(ctx);
423         if (r < 0)
424                 return r;
425
426         name = udev_device_get_sysname(device);
427         if (!name)
428                 return -EINVAL;
429
430         r = ethtool_get_driver(ctx->ethtool_fd, name, &driver);
431         if (r < 0)
432                 return r;
433
434         *ret = driver;
435         return 0;
436 }
437
438 static const char* const mac_policy_table[_MACPOLICY_MAX] = {
439         [MACPOLICY_PERSISTENT] = "persistent",
440         [MACPOLICY_RANDOM] = "random"
441 };
442
443 DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
444 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
445
446 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
447         [NAMEPOLICY_DATABASE] = "database",
448         [NAMEPOLICY_ONBOARD] = "onboard",
449         [NAMEPOLICY_SLOT] = "slot",
450         [NAMEPOLICY_PATH] = "path",
451         [NAMEPOLICY_MAC] = "mac"
452 };
453
454 DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
455 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");