link-config.c revision 9a4b012e43f23516373bf398dd9a458439d19939
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <netinet/ether.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <linux/netdevice.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-id128.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "missing.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "link-config.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "ethtool-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "libudev-private.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-rtnl.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "path-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "conf-parser.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "conf-files.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "fileio.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "hashmap.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "rtnl-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "network-internal.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "siphash24.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstruct link_config_ctx {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_HEAD(link_config, links);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int ethtool_fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool enable_name_policy;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_rtnl *rtnl;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering usec_t link_dirs_ts_usec;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char* const link_dirs[] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/etc/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/run/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/usr/lib/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SPLIT_USR
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/lib/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NULL};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void link_config_free(link_config *link) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!link)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_mac);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_driver);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_host);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_virt);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_kernel);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_arch);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->description);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->mac);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->name_policy);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->alias);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_config *link, *link_next;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!ctx)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_config_free(link);
aba8b84e8d72224445b67646974b9dabc0972187Dave Reisner}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!ctx)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(ctx->ethtool_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_rtnl_unref(ctx->rtnl);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_configs_free(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!ret)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ctx = new0(link_config_ctx, 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!ctx)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_HEAD_INIT(ctx->links);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ctx->ethtool_fd = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ctx->enable_name_policy = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = ctx;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ctx = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(link_config_freep) link_config *link = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_fclose_ FILE *file = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering file = fopen(filename, "re");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!file) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno == ENOENT)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (null_or_empty_fd(fileno(file))) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Skipping empty file: %s", filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link = new0(link_config, 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!link)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_oom();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->mac_policy = _MACPOLICY_INVALID;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->wol = _WOL_INVALID;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->duplex = _DUP_INVALID;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = config_parse(NULL, filename, file,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "Match\0Link\0Ethernet\0",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering config_item_perf_lookup, link_config_gperf_lookup,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering false, false, true, link);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Parsed configuration file %s", filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename = strdup(filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_PREPEND(links, ctx->links, link);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool enable_name_policy(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *line = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *word, *state;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = proc_cmdline(&line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering FOREACH_WORD_QUOTED(word, l, line, state)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (strneq(word, "net.ifnames=0", l))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_strv_free_ char **files;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char **f;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_configs_free(ctx);
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering if (!enable_name_policy()) {
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering ctx->enable_name_policy = false;
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering }
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering /* update timestamp */
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering if (r < 0)
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering return log_error_errno(r, "failed to enumerate link files: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = load_link(ctx, *f);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringbool link_config_should_reload(link_config_ctx *ctx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_config **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_config *link;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH(links, link, ctx->links) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char* attr_value;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering attr_value = udev_device_get_sysattr_value(device, "address");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (net_match_config(link->match_mac, link->match_path, link->match_driver,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->match_type, link->match_name, link->match_host,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->match_virt, link->match_kernel, link->match_arch,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering attr_value ? ether_aton(attr_value) : NULL,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_property_value(device, "ID_PATH"),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_driver(udev_device_get_parent(device)),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_property_value(device, "ID_NET_DRIVER"),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_devtype(device),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_sysname(device))) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (link->match_name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned char name_assign_type = NET_NAME_UNKNOWN;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (attr_value)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (void)safe_atou8(attr_value, &name_assign_type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (name_assign_type == NET_NAME_ENUM) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename, udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = link;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (name_assign_type == NET_NAME_RENAMED) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename, udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering continue;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Config file %s applies to device %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename, udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = link;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOENT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned type;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* if we can't get the assign type, assume it is not random */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s = udev_device_get_sysattr_value(device, "addr_assign_type");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atou(s, &type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return type == NET_ADDR_RANDOM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool should_rename(struct udev_device *device, bool respect_predictable) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned type;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* if we can't get the assgin type, assume we should rename */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s = udev_device_get_sysattr_value(device, "name_assign_type");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atou(s, &type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (type) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_USER:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_RENAMED:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* these were already named by userspace, do not touch again */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_PREDICTABLE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* the kernel claims to have given a predictable name */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (respect_predictable)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* fall through */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_ENUM:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering default:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* the name is known to be bad, or of an unknown type */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct ether_addr *mac) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (want_random)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint8_t result[8];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = net_get_unique_predictable_data(device, result);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_cc(ETH_ALEN <= sizeof(result));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* see eth_random_addr in the kernel */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct udev_device *device, const char **name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *old_name;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *new_name = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct ether_addr generated_mac;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct ether_addr *mac = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool respect_predictable = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r, ifindex;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(config);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name = udev_device_get_sysname(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!old_name)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering config->duplex);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name, config->speed / 1024,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering duplex_to_string(config->duplex));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name, wol_to_string(config->wol));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ifindex = udev_device_get_ifindex(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ifindex <= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not find ifindex");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENODEV;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ctx->enable_name_policy && config->name_policy) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NamePolicy *policy;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (policy = config->name_policy;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (*policy) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NAMEPOLICY_KERNEL:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering respect_predictable = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NAMEPOLICY_DATABASE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NAMEPOLICY_ONBOARD:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NAMEPOLICY_SLOT:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NAMEPOLICY_PATH:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
case NAMEPOLICY_MAC:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
break;
default:
break;
}
}
}
if (should_rename(device, respect_predictable)) {
/* if not set by policy, fall back manually set name */
if (!new_name)
new_name = config->name;
} else
new_name = NULL;
switch (config->mac_policy) {
case MACPOLICY_PERSISTENT:
if (mac_is_random(device)) {
r = get_mac(device, false, &generated_mac);
if (r == -ENOENT)
break;
else if (r < 0)
return r;
mac = &generated_mac;
}
break;
case MACPOLICY_RANDOM:
if (!mac_is_random(device)) {
r = get_mac(device, true, &generated_mac);
if (r == -ENOENT)
break;
else if (r < 0)
return r;
mac = &generated_mac;
}
break;
default:
mac = config->mac;
}
r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac,
config->mtu);
if (r < 0)
return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
*name = new_name;
return 0;
}
int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
const char *name;
char *driver;
int r;
name = udev_device_get_sysname(device);
if (!name)
return -EINVAL;
r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
if (r < 0)
return r;
*ret = driver;
return 0;
}
static const char* const mac_policy_table[_MACPOLICY_MAX] = {
[MACPOLICY_PERSISTENT] = "persistent",
[MACPOLICY_RANDOM] = "random"
};
DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
"Failed to parse MAC address policy");
static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
[NAMEPOLICY_KERNEL] = "kernel",
[NAMEPOLICY_DATABASE] = "database",
[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");