link-config.c revision edf029b7fd9a5853a87d3ca99aac2922bb8a277e
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 <net/if.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-id128.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering#include "link-config.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "ethtool-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "libudev-private.h"
96aad8d15a324d0e956a4e5653a11a67b209b41aLennart Poettering#include "sd-rtnl.h"
23c80348e656a4e6fd9ba8f17523a65b6fa349a0Kay Sievers#include "util.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "log.h"
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering#include "strv.h"
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering#include "path-util.h"
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering#include "conf-parser.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "conf-files.h"
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering#include "fileio.h"
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier#include "hashmap.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "rtnl-util.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "network-internal.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "siphash24.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstruct link_config_ctx {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering LIST_HEAD(link_config, links);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering int ethtool_fd;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering bool enable_name_policy;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering sd_rtnl *rtnl;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering usec_t link_dirs_ts_usec;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering};
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic const char* const link_dirs[] = {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering "/etc/systemd/network",
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering "/run/systemd/network",
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering "/usr/lib/systemd/network",
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#ifdef HAVE_SPLIT_USR
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering "/lib/systemd/network",
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#endif
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering NULL};
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (!ret)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -EINVAL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering ctx = new0(link_config_ctx, 1);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (!ctx)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -ENOMEM;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering LIST_HEAD_INIT(ctx->links);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering ctx->ethtool_fd = -1;
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering ctx->enable_name_policy = true;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering *ret = ctx;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering ctx = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering}
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic int link_config_ctx_connect(link_config_ctx *ctx) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering int r;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (ctx->ethtool_fd == -1) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = ethtool_connect(&ctx->ethtool_fd);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (r < 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return r;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (!ctx->rtnl) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = sd_rtnl_open(&ctx->rtnl, 0);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (r < 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return r;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering}
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering link_config *link, *link_next;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (!ctx)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link->filename);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link->match_path);
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering free(link->match_driver);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link->match_type);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link->description);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link->alias);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link->name_policy);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering free(link);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering}
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (!ctx)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering safe_close(ctx->ethtool_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering sd_rtnl_unref(ctx->rtnl);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link_configs_free(ctx);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering free(ctx);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_free_ link_config *link = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_fclose_ FILE *file = NULL;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(ctx);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(filename);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (null_or_empty_path(filename)) {
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering log_debug("skipping empty file: %s", filename);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering file = fopen(filename, "re");
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (!file) {
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (errno == ENOENT)
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return 0;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering else
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return -errno;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering }
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering link = new0(link_config, 1);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (!link)
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return log_oom();
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering link->mac_policy = _MACPOLICY_INVALID;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering link->wol = _WOL_INVALID;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering link->duplex = _DUP_INVALID;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering (void*) link_config_gperf_lookup, false, false, link);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (r < 0) {
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering log_warning("Could not parse config file %s: %s", filename, strerror(-r));
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return r;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering } else
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering log_debug("Parsed configuration file %s", filename);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering link->filename = strdup(filename);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering LIST_PREPEND(links, ctx->links, link);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic bool enable_name_policy(void) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_free_ char *line;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char *w, *state;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering size_t l;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering r = proc_cmdline(&line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (r <= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return true;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering FOREACH_WORD_QUOTED(w, l, line, state)
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering if (strneq(w, "net.ifnames=0", l))
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering return false;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering return true;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering}
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int r;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering _cleanup_strv_free_ char **files;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering char **f;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link_configs_free(ctx);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!enable_name_policy()) {
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek ctx->enable_name_policy = false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* update timestamp */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering log_error("failed to enumerate link files: %s", strerror(-r));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = load_link(ctx, *f);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringbool link_config_should_reload(link_config_ctx *ctx) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link_config *link;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_FOREACH(links, link, ctx->links) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (net_match_config(link->match_mac, link->match_path, link->match_driver,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link->match_type, NULL, link->match_host,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering link->match_virt, link->match_kernel, link->match_arch,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ether_aton(udev_device_get_sysattr_value(device, "address")),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_property_value(device, "ID_PATH"),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_driver(udev_device_get_parent(device)),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_property_value(device, "ID_NET_DRIVER"),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_devtype(device),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering NULL)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug("Config file %s applies to device %s",
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering link->filename,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = link;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *ret = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -ENOENT;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering}
8aec412ff697bc14995746953912ca6fdf2c9ba8Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned type;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s = udev_device_get_sysattr_value(device, "addr_assign_type");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (!s)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return false; /* if we don't know, assume it is not random */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atou(s, &type);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return false;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* check for NET_ADDR_RANDOM */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return type == 1;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
7f0d207d2c816e0a8cb2742b0a789911f7c99356Lennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (want_random)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart 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;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_cc(ETH_ALEN <= sizeof(result));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* see eth_random_addr in the kernel */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return 0;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering}
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering const char *old_name;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering const char *new_name = NULL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering struct ether_addr generated_mac;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering struct ether_addr *mac = NULL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering int r, ifindex;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(ctx);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(config);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = link_config_ctx_connect(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name = udev_device_get_sysname(device);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!old_name)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering old_name, config->speed / 1024, duplex_to_string(config->duplex),
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering strerror(-r));
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering if (r < 0)
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering log_warning("Could not set WakeOnLan of %s to %s: %s",
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering old_name, wol_to_string(config->wol), strerror(-r));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering ifindex = udev_device_get_ifindex(device);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering if (ifindex <= 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Could not find ifindex");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -ENODEV;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ctx->enable_name_policy && config->name_policy) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering NamePolicy *policy;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (*policy) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart 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;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering case NAMEPOLICY_PATH:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NAMEPOLICY_MAC:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering default:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (new_name)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering *name = new_name; /* a name was set by a policy */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering else if (config->name)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering *name = config->name; /* a name was set manually in the config */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering else
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering *name = NULL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering switch (config->mac_policy) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering case MACPOLICY_PERSISTENT:
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (mac_is_random(device)) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = get_mac(device, false, &generated_mac);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering mac = &generated_mac;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering break;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering case MACPOLICY_RANDOM:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (!mac_is_random(device)) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = get_mac(device, true, &generated_mac);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering mac = &generated_mac;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering break;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering default:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering mac = config->mac;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return 0;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering const char *name;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char *driver;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek r = link_config_ctx_connect(ctx);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering name = udev_device_get_sysname(device);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (!name)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return -EINVAL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = ethtool_get_driver(ctx->ethtool_fd, name, &driver);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (r < 0)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return r;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering *ret = driver;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return 0;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering}
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic const char* const mac_policy_table[_MACPOLICY_MAX] = {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering [MACPOLICY_PERSISTENT] = "persistent",
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering [MACPOLICY_RANDOM] = "random"
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering};
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic const char* const name_policy_table[_NAMEPOLICY_MAX] = {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering [NAMEPOLICY_DATABASE] = "database",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering [NAMEPOLICY_ONBOARD] = "onboard",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering [NAMEPOLICY_SLOT] = "slot",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering [NAMEPOLICY_PATH] = "path",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering [NAMEPOLICY_MAC] = "mac"
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering};
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering