link-config.c revision 58c9846d32e55799b6e4607136a34e2727c919ac
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
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"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "libudev-private.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-rtnl.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "path-util.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "conf-parser.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "conf-files.h"
c34255bdb217c2a1d3ac6348252437ab8be9ca46Lennart Poettering#include "fileio.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "hashmap.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "rtnl-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "network-internal.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart 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;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt bool enable_name_policy;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_rtnl *rtnl;
d3e84ddb885e9d5f0ae9930eb905910e3a81f157Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering usec_t link_dirs_ts_usec;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering};
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic const char* const link_dirs[] = {
afc6adb5ec7e73bc13156c43f52fb015cd80cc68Lennart Poettering "/etc/systemd/network",
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering "/run/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/usr/lib/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SPLIT_USR
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/lib/systemd/network",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
cde93897cdefdd7c7f66c400a61e42ceee5f6a46Lennart Poettering NULL};
cde93897cdefdd7c7f66c400a61e42ceee5f6a46Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_link_config_ctx_free_ 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
d3e84ddb885e9d5f0ae9930eb905910e3a81f157Lennart Poettering LIST_HEAD_INIT(ctx->links);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ctx->ethtool_fd = -1;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ctx->enable_name_policy = true;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *ret = ctx;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ctx = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
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 free(link->filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_driver);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->match_type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->description);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->alias);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link->name_policy);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(link);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering if (!ctx)
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering return;
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering safe_close(ctx->ethtool_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_rtnl_unref(ctx->rtnl);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_configs_free(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(ctx);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ 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");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!file) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno == ENOENT)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
76b543756ef69ce69784d571aefe8de65eaeb331Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (null_or_empty_fd(fileno(file))) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_debug("Skipping empty file: %s", filename);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering link = new0(link_config, 1);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!link)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt return log_oom();
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->mac_policy = _MACPOLICY_INVALID;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->wol = _WOL_INVALID;
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering link->duplex = _DUP_INVALID;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = config_parse(NULL, filename, file,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "Match\0Link\0Ethernet\0",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering config_item_perf_lookup, link_config_gperf_lookup,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering false, false, true, link);
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt else
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug("Parsed configuration file %s", filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename = strdup(filename);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering LIST_PREPEND(links, ctx->links, link);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic bool enable_name_policy(void) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_free_ char *line = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering const char *word, *state;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering size_t l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = proc_cmdline(&line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering strerror(-r));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r <= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return true;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering FOREACH_WORD_QUOTED(word, l, line, state)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (strneq(word, "net.ifnames=0", l))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt return true;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poetteringint link_config_load(link_config_ctx *ctx) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int r;
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering _cleanup_strv_free_ char **files;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char **f;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link_configs_free(ctx);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!enable_name_policy()) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ctx->enable_name_policy = false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* update timestamp */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart 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)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart 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,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link_config **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_config *link;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_FOREACH(links, link, ctx->links) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char* attr_value = udev_device_get_sysattr_value(device, "address");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
5bb658a1784a0fd4f0f32adb4b1fb636ff503f7dKay Sievers if (net_match_config(link->match_mac, link->match_path, link->match_driver,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link->match_type, NULL, link->match_host,
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt link->match_virt, link->match_kernel, link->match_arch,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart 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)),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_property_value(device, "ID_NET_DRIVER"),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_devtype(device),
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt NULL)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug("Config file %s applies to device %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = link;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOENT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
71fda00f320379f5cbee8e118848de98caaa229dLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart 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)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart 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)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (type) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_USER:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_RENAMED:
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* these were already named by userspace, do not touch again */
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_PREDICTABLE:
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* the kernel claims to have given a predictable name */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (respect_predictable)
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering return false;
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* fall through */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case NET_NAME_ENUM:
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering default:
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* the name is known to be bad, or of an unknown type */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return true;
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering }
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering}
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random,
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering struct ether_addr *mac) {
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart 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
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering struct udev_device *device, const char **name) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart 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);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name = udev_device_get_sysname(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!old_name)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek
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("Could not set speed or duplex of %s to %u Mbps (%s): %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name, config->speed / 1024,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering duplex_to_string(config->duplex), strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not set WakeOnLan of %s to %s: %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name, wol_to_string(config->wol), strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ifindex = udev_device_get_ifindex(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ifindex <= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not find ifindex");
return -ENODEV;
}
if (ctx->enable_name_policy && config->name_policy) {
NamePolicy *policy;
for (policy = config->name_policy;
!new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
switch (*policy) {
case NAMEPOLICY_KERNEL:
respect_predictable = true;
break;
case NAMEPOLICY_DATABASE:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
break;
case NAMEPOLICY_ONBOARD:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
break;
case NAMEPOLICY_SLOT:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
break;
case NAMEPOLICY_PATH:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
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) {
log_warning("Could not set Alias, MACAddress or MTU on %s: %s",
old_name, strerror(-r));
return r;
}
*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");