link-config.c revision f8a0bb5285024b6ce372c3157e761e6543ebdcd2
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/***
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen***/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <netinet/ether.h>
2a73e0d39a9bec82c3800071e375d27164727e71Tom Gundersen#include <net/if.h>
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen#include "sd-id128.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen#include "link-config.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#include "ethtool-util.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "libudev-private.h"
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "sd-rtnl.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "util.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "log.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "strv.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "path-util.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "conf-parser.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "conf-files.h"
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen#include "fileio.h"
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen#include "hashmap.h"
3aeb37bc4f32b5edc334f2ac7c5d3c7b0a121328Tom Gundersen#include "rtnl-util.h"
c6f7c917a1b494d4455800823472227463f87438Tom Gundersen#include "network-internal.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "siphash24.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstruct link_config_ctx {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen LIST_HEAD(link_config, links);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen int ethtool_fd;
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen bool enable_name_policy;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen sd_rtnl *rtnl;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen usec_t link_dirs_ts_usec;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen};
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmekstatic const char* const link_dirs[] = {
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek "/etc/systemd/network",
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek "/run/systemd/network",
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek "/usr/lib/systemd/network",
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek#ifdef HAVE_SPLIT_USR
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek "/lib/systemd/network",
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek#endif
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek NULL};
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom GundersenDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint link_config_ctx_new(link_config_ctx **ret) {
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!ret)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return -EINVAL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen ctx = new0(link_config_ctx, 1);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!ctx)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return -ENOMEM;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen LIST_HEAD_INIT(ctx->links);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen ctx->ethtool_fd = -1;
977085794d2996320e345433403de75f662b0622Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen ctx->enable_name_policy = true;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen *ret = ctx;
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen ctx = NULL;
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersenstatic int link_config_ctx_connect(link_config_ctx *ctx) {
977085794d2996320e345433403de75f662b0622Tom Gundersen int r;
977085794d2996320e345433403de75f662b0622Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (ctx->ethtool_fd == -1) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen r = ethtool_connect(&ctx->ethtool_fd);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (r < 0)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return r;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen }
977085794d2996320e345433403de75f662b0622Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (!ctx->rtnl) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen r = sd_rtnl_open(&ctx->rtnl, 0);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (r < 0)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return r;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen }
977085794d2996320e345433403de75f662b0622Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen return 0;
977085794d2996320e345433403de75f662b0622Tom Gundersen}
977085794d2996320e345433403de75f662b0622Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic void link_configs_free(link_config_ctx *ctx) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen link_config *link, *link_next;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!ctx)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(link->filename);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(link->match_path);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(link->match_driver);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(link->match_type);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(link->description);
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen free(link->alias);
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen free(link->name_policy);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(link);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenvoid link_config_ctx_free(link_config_ctx *ctx) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!ctx)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering safe_close(ctx->ethtool_fd);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen sd_rtnl_unref(ctx->rtnl);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen link_configs_free(ctx);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(ctx);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int load_link(link_config_ctx *ctx, const char *filename) {
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek _cleanup_free_ link_config *link = NULL;
6e37cd2f4af8928d905203108a4331e375d7127cThomas Hindoe Paaboel Andersen _cleanup_fclose_ FILE *file = NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen int r;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen assert(ctx);
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen assert(filename);
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen
6916ec29afd488d91e7e0fcbcc2e006b4e5f28dfTom Gundersen if (null_or_empty_path(filename)) {
6916ec29afd488d91e7e0fcbcc2e006b4e5f28dfTom Gundersen log_debug("skipping empty file: %s", filename);
6916ec29afd488d91e7e0fcbcc2e006b4e5f28dfTom Gundersen return 0;
6916ec29afd488d91e7e0fcbcc2e006b4e5f28dfTom Gundersen }
6916ec29afd488d91e7e0fcbcc2e006b4e5f28dfTom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen file = fopen(filename, "re");
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!file) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (errno == ENOENT)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen else
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek return -errno;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen link = new0(link_config, 1);
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if (!link)
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek return log_oom();
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen link->mac_policy = _MACPOLICY_INVALID;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen link->wol = _WOL_INVALID;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen link->duplex = _DUP_INVALID;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (void*) link_config_gperf_lookup, false, false, link);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r < 0) {
489124365d1d391864898b9869dd668eea5b2e28Dave Reisner log_warning("Could not parse config file %s: %s", filename, strerror(-r));
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek return r;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen } else
98a375f6d5cac24eb80d6d4e00699851324afdecTom Gundersen log_debug("Parsed configuration file %s", filename);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen link->filename = strdup(filename);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen LIST_PREPEND(links, ctx->links, link);
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek link = NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersenstatic bool enable_name_policy(void) {
f8a0bb5285024b6ce372c3157e761e6543ebdcd2Andreas Henriksson _cleanup_free_ char *line = NULL;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen char *w, *state;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen int r;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen size_t l;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering r = proc_cmdline(&line);
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering if (r < 0)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering if (r <= 0)
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering return true;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen FOREACH_WORD_QUOTED(w, l, line, state)
ff83aac3647e21f31ac5e2b575ec1285dc585f6bTom Gundersen if (strneq(w, "net.ifnames=0", l))
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return false;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return true;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen}
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint link_config_load(link_config_ctx *ctx) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen int r;
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen _cleanup_strv_free_ char **files;
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen char **f;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen link_configs_free(ctx);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (!enable_name_policy()) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen ctx->enable_name_policy = false;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen }
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen /* update timestamp */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r < 0) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen log_error("failed to enumerate link files: %s", strerror(-r));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return r;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen STRV_FOREACH_BACKWARDS(f, files) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = load_link(ctx, *f);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r < 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return r;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenbool link_config_should_reload(link_config_ctx *ctx) {
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen link_config *link;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen LIST_FOREACH(links, link, ctx->links) {
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen if (net_match_config(link->match_mac, link->match_path, link->match_driver,
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen link->match_type, NULL, link->match_host,
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen link->match_virt, link->match_kernel, link->match_arch,
505f8da7325591defe5f751f328bd26915267602Tom Gundersen ether_aton(udev_device_get_sysattr_value(device, "address")),
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen udev_device_get_property_value(device, "ID_PATH"),
9b1c2626cef16722603bded9bb52033aba34dd74Tom Gundersen udev_device_get_driver(udev_device_get_parent(device)),
bf175aafd20c9ef974709ef12c5acf836121af33Tom Gundersen udev_device_get_property_value(device, "ID_NET_DRIVER"),
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen udev_device_get_devtype(device),
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen NULL)) {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen log_debug("Config file %s applies to device %s",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen link->filename,
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen udev_device_get_sysname(device));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen *ret = link;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen *ret = NULL;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return -ENOENT;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic bool mac_is_random(struct udev_device *device) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen const char *s;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen unsigned type;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen int r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen s = udev_device_get_sysattr_value(device, "addr_assign_type");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!s)
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen return false; /* if we don't know, assume it is not random */
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen r = safe_atou(s, &type);
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen if (r < 0)
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen return false;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen /* check for NET_ADDR_RANDOM */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return type == 1;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen}
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersenstatic int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering int r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (want_random)
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen else {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering uint8_t result[8];
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
b5db00e52ee2e20578839e4e4488f7b9af9abc38Umut Tezduyar Lindskog r = net_get_unique_predictable_data(device, result);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (r < 0)
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen return r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering assert_cc(ETH_ALEN <= sizeof(result));
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen /* see eth_random_addr in the kernel */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return 0;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen}
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersenint link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen const char *old_name;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen const char *new_name = NULL;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen struct ether_addr generated_mac;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen struct ether_addr *mac = NULL;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen int r, ifindex;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen assert(ctx);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen assert(config);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen assert(device);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen assert(name);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen r = link_config_ctx_connect(ctx);
977085794d2996320e345433403de75f662b0622Tom Gundersen if (r < 0)
977085794d2996320e345433403de75f662b0622Tom Gundersen return r;
977085794d2996320e345433403de75f662b0622Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen old_name = udev_device_get_sysname(device);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (!old_name)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return -EINVAL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (r < 0)
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen old_name, config->speed / 1024, duplex_to_string(config->duplex),
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen strerror(-r));
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (r < 0)
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_warning("Could not set WakeOnLan of %s to %s: %s",
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen old_name, wol_to_string(config->wol), strerror(-r));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen ifindex = udev_device_get_ifindex(device);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen if (ifindex <= 0) {
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen log_warning("Could not find ifindex");
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return -ENODEV;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen }
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (ctx->enable_name_policy && config->name_policy) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen NamePolicy *policy;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen switch (*policy) {
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen case NAMEPOLICY_DATABASE:
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case NAMEPOLICY_ONBOARD:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case NAMEPOLICY_SLOT:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case NAMEPOLICY_PATH:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case NAMEPOLICY_MAC:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen default:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen }
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen }
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (new_name)
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen *name = new_name; /* a name was set by a policy */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen else if (config->name)
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen *name = config->name; /* a name was set manually in the config */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen else
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen *name = NULL;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen switch (config->mac_policy) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case MACPOLICY_PERSISTENT:
92d927f850d4b668b44f3e5f41e266d934d03726Tom Gundersen if (mac_is_random(device)) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen r = get_mac(device, false, &generated_mac);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (r < 0)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return r;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen mac = &generated_mac;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case MACPOLICY_RANDOM:
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!mac_is_random(device)) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen r = get_mac(device, true, &generated_mac);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (r < 0)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return r;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen mac = &generated_mac;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen break;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen default:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen mac = config->mac;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen if (r < 0) {
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return r;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen }
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenint link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen const char *name;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen char *driver;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen int r;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen r = link_config_ctx_connect(ctx);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (r < 0)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return r;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen name = udev_device_get_sysname(device);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (!name)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return -EINVAL;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen r = ethtool_get_driver(ctx->ethtool_fd, name, &driver);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (r < 0)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return r;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen *ret = driver;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return 0;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen}
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mackstatic const char* const mac_policy_table[_MACPOLICY_MAX] = {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen [MACPOLICY_PERSISTENT] = "persistent",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen [MACPOLICY_RANDOM] = "random"
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen};
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mackstatic const char* const name_policy_table[_NAMEPOLICY_MAX] = {
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen [NAMEPOLICY_DATABASE] = "database",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen [NAMEPOLICY_ONBOARD] = "onboard",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen [NAMEPOLICY_SLOT] = "slot",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen [NAMEPOLICY_PATH] = "path",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen [NAMEPOLICY_MAC] = "mac"
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen};
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");