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