link-config.c revision a669ea9860900d5cdebbc4cb9aaea72db7e28a02
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/***
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering This file is part of systemd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is free software; you can redistribute it and/or modify it
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering under the terms of the GNU Lesser General Public License as published by
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (at your option) any later version.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is distributed in the hope that it will be useful, but
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Lesser General Public License for more details.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering You should have received a copy of the GNU Lesser General Public License
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering***/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <netinet/ether.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <net/if.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "sd-id128.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "link-config.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "ethtool-util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "libudev-private.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "sd-rtnl.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "log.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "strv.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "path-util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "conf-parser.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "conf-files.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "fileio.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "hashmap.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "rtnl-util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "network-internal.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "siphash24.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstruct link_config_ctx {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD(link_config, links);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int ethtool_fd;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering bool enable_name_policy;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_rtnl *rtnl;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering usec_t link_dirs_ts_usec;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering};
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic const char* const link_dirs[] = {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "/etc/systemd/network",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "/run/systemd/network",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "/usr/lib/systemd/network",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#ifdef HAVE_SPLIT_USR
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "/lib/systemd/network",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#endif
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering NULL};
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!ret)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ctx = new0(link_config_ctx, 1);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!ctx)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOMEM;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD_INIT(ctx->links);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ctx->ethtool_fd = -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ctx->enable_name_policy = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = ctx;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ctx = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int link_config_ctx_connect(link_config_ctx *ctx) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (ctx->ethtool_fd == -1) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = ethtool_connect(&ctx->ethtool_fd);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("link_config: could not connect to ethtool: %s",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!ctx->rtnl) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = sd_rtnl_open(&ctx->rtnl, 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("link_config: could not connect to rtnl: %s",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link_config *link, *link_next;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!ctx)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->match_path);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->match_driver);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->match_type);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->description);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->alias);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link->name_policy);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(link);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!ctx)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering safe_close(ctx->ethtool_fd);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_rtnl_unref(ctx->rtnl);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link_configs_free(ctx);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(ctx);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_free_ link_config *link = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_fclose_ FILE *file = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(ctx);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (null_or_empty_path(filename)) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("skipping empty file: %s", filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering file = fopen(filename, "re");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!file) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (errno == ENOENT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -errno;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link = new0(link_config, 1);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!link)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->mac_policy = _MACPOLICY_INVALID;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->wol = _WOL_INVALID;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->duplex = _DUP_INVALID;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (void*) link_config_gperf_lookup, false, false, link);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Could not parse config file %s: %s", filename, strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering } else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Parsed configuration file %s", filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->filename = strdup(filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_PREPEND(links, ctx->links, link);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic bool enable_name_policy(void) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_free_ char *line = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char *w, *state;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering size_t l;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = proc_cmdline(&line);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r <= 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering FOREACH_WORD_QUOTED(w, l, line, state)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (strneq(w, "net.ifnames=0", l))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return false;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_strv_free_ char **files;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char **f;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link_configs_free(ctx);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!enable_name_policy()) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ctx->enable_name_policy = false;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* update timestamp */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("failed to enumerate link files: %s", strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = load_link(ctx, *f);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
c5285fbfcede2e0f54d2b5f14193041067cd2af6David Herrmann return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringbool link_config_should_reload(link_config_ctx *ctx) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link_config *link;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH(links, link, ctx->links) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (net_match_config(link->match_mac, link->match_path, link->match_driver,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->match_type, NULL, link->match_host,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->match_virt, link->match_kernel, link->match_arch,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ether_aton(udev_device_get_sysattr_value(device, "address")),
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_device_get_property_value(device, "ID_PATH"),
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_device_get_driver(udev_device_get_parent(device)),
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_device_get_property_value(device, "ID_NET_DRIVER"),
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_device_get_devtype(device),
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering NULL)) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Config file %s applies to device %s",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->filename,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_device_get_sysname(device));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = link;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOENT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *s;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering unsigned type;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering s = udev_device_get_sysattr_value(device, "addr_assign_type");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!s)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return false; /* if we don't know, assume it is not random */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = safe_atou(s, &type);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return false;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* check for NET_ADDR_RANDOM */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return type == 1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (want_random)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering uint8_t result[8];
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = net_get_unique_predictable_data(device, result);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert_cc(ETH_ALEN <= sizeof(result));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* see eth_random_addr in the kernel */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *old_name;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *new_name = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct ether_addr generated_mac;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct ether_addr *mac = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r, ifindex;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(ctx);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(config);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(device);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = link_config_ctx_connect(ctx);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering old_name = udev_device_get_sysname(device);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!old_name)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering old_name, config->speed / 1024, duplex_to_string(config->duplex),
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Could not set WakeOnLan of %s to %s: %s",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering old_name, wol_to_string(config->wol), strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ifindex = udev_device_get_ifindex(device);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (ifindex <= 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Could not find ifindex");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENODEV;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (ctx->enable_name_policy && config->name_policy) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering NamePolicy *policy;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering switch (*policy) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case NAMEPOLICY_DATABASE:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case NAMEPOLICY_ONBOARD:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case NAMEPOLICY_SLOT:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case NAMEPOLICY_PATH:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case NAMEPOLICY_MAC:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering default:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (new_name)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *name = new_name; /* a name was set by a policy */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (config->name)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *name = config->name; /* a name was set manually in the config */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *name = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering switch (config->mac_policy) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case MACPOLICY_PERSISTENT:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (mac_is_random(device)) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = get_mac(device, false, &generated_mac);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r == -ENOENT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering mac = &generated_mac;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering case MACPOLICY_RANDOM:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!mac_is_random(device)) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = get_mac(device, true, &generated_mac);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r == -ENOENT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering mac = &generated_mac;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering default:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering mac = config->mac;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering const char *name;
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poettering char *driver;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering int r;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering r = link_config_ctx_connect(ctx);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (r < 0)
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return r;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering name = udev_device_get_sysname(device);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (!name)
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return -EINVAL;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering r = ethtool_get_driver(ctx->ethtool_fd, name, &driver);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (r < 0)
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return r;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering *ret = driver;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return 0;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering}
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poetteringstatic const char* const mac_policy_table[_MACPOLICY_MAX] = {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering [MACPOLICY_PERSISTENT] = "persistent",
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering [MACPOLICY_RANDOM] = "random"
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering};
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poetteringstatic const char* const name_policy_table[_NAMEPOLICY_MAX] = {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering [NAMEPOLICY_DATABASE] = "database",
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering [NAMEPOLICY_ONBOARD] = "onboard",
[NAMEPOLICY_SLOT] = "slot",
[NAMEPOLICY_PATH] = "path",
[NAMEPOLICY_MAC] = "mac"
};
DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");