link-config.c revision 97f2d76d4f4dfab8b0629c09926a05a1e5621125
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <netinet/ether.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <net/if.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "sd-id128.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "link-config.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "ethtool-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "libudev-private.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "sd-rtnl.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "log.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "strv.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "path-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "conf-parser.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "conf-files.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "fileio.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "hashmap.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct link_config_ctx {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_HEAD(link_config, links);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int ethtool_fd;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_rtnl *rtnl;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char **link_dirs;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t link_dirs_ts_usec;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering};
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering link_config_ctx *ctx;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering int r;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!ret)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EINVAL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ctx = new0(link_config_ctx, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!ctx)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = ethtool_connect(&ctx->ethtool_fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config_ctx_free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_rtnl_open(0, &ctx->rtnl);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config_ctx_free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_HEAD_INIT(ctx->links);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ctx->link_dirs = strv_new("/etc/systemd/network",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/run/systemd/network",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/usr/lib/systemd/network",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!ctx->link_dirs) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("failed to build link config directory array");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config_ctx_free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!path_strv_canonicalize_uniq(ctx->link_dirs)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("failed to canonicalize link config directories\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config_ctx_free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ret = ctx;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config *link, *link_next;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!ctx)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link->filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link->match_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link->match_driver);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link->match_type);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link->description);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!ctx)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (ctx->ethtool_fd >= 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering close_nointr_nofail(ctx->ethtool_fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_rtnl_unref(ctx->rtnl);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free(ctx->link_dirs);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_configs_free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config *link;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FILE *file;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering file = fopen(filename, "re");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!file) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (errno == ENOENT)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return errno;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link = new0(link_config, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!link) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = log_oom();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto failure;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link->mac_policy = _MACPOLICY_INVALID;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link->wol = _WOL_INVALID;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link->duplex = _DUP_INVALID;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (void*) link_config_gperf_lookup, false, false, link);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Colud not parse config file %s: %s", filename, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto failure;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Parsed configuration file %s", filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link->filename = strdup(filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(links, ctx->links, link);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringfailure:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(link);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char **files, **f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_configs_free(ctx);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* update timestamp */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering paths_check_timestamp(ctx->link_dirs, &ctx->link_dirs_ts_usec, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, (const char **)ctx->link_dirs);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("failed to enumerate link files: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = load_link(ctx, *f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringbool link_config_should_reload(link_config_ctx *ctx) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return paths_check_timestamp(ctx->link_dirs, &ctx->link_dirs_ts_usec, false);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool match_config(link_config *match, struct udev_device *device) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *property;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (match->match_mac) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property = udev_device_get_sysattr_value(device, "address");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!property || memcmp(match->match_mac, ether_aton(property), ETH_ALEN)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Device MAC address (%s) did not match MACAddress=%s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property, ether_ntoa(match->match_mac));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (match->match_path) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property = udev_device_get_property_value(device, "ID_PATH");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!streq_ptr(match->match_path, property)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Device's persistent path (%s) did not match Path=%s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property, match->match_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (match->match_driver) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property = udev_device_get_driver(device);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!streq_ptr(match->match_driver, property)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Device driver (%s) did not match Driver=%s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property, match->match_driver);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (match->match_type) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property = udev_device_get_devtype(device);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!streq_ptr(match->match_type, property)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Device type (%s) did not match Type=%s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering property, match->match_type);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering link_config *link;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(links, link, ctx->links) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!match_config(link, device)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Config file %s does not apply to device %s", link->filename, udev_device_get_sysname(device));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Config file %s applies to device %s", link->filename, udev_device_get_sysname(device));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ret = link;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOENT;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int rtnl_set_properties(sd_rtnl *rtnl, int ifindex, const char *name, const struct ether_addr *mac, unsigned int mtu) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool need_update = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rtnl);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(ifindex > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_rtnl_message_link_new(RTM_NEWLINK, ifindex, 0, 0, &message);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (name) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek r = sd_rtnl_message_append(message, IFLA_IFNAME, name);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering need_update = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (mac) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_rtnl_message_append(message, IFLA_ADDRESS, mac);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering need_update = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (mtu > 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_rtnl_message_append(message, IFLA_MTU, &mtu);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering need_update = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (need_update) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_rtnl_send_with_reply_and_block(rtnl, message, 5 * USEC_PER_SEC, NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
7850b3b83791ba0e2377ba40383c5abc258b839dKay Sievers }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool enable_name_policy(void) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_free_ char *line;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *w, *state;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t l;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = read_one_line_file("/proc/cmdline", &line);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return true; /* something is very wrong, let's not make it worse */
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek }
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FOREACH_WORD_QUOTED(w, l, line, state)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (strneq(w, "net.ifnames=0", l))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *s;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int type;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering s = udev_device_get_sysattr_value(device, "addr_assign_type");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!s)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EINVAL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering type = strtoul(s, NULL, 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* check for NET_ADDR_RANDOM */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return type == 1;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek}
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmekstatic bool mac_is_permanent(struct udev_device *device) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek const char *s;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek int type;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek s = udev_device_get_sysattr_value(device, "addr_assign_type");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!s)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return -EINVAL;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek type = strtoul(s, NULL, 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* check for NET_ADDR_PERM */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return type == 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering unsigned int seed;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering int r, i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (want_random)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering seed = random_u();
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *name;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_id128_t machine;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char machineid_buf[33];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *seed_str;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek /* fetch some persistent data unique (on this machine) to this device */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!name) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!name) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (!name)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* fetch some persistent data unique to this machine */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_id128_get_machine(&machine);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* combine the data */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering seed_str = strappenda(name, sd_id128_to_string(machine, machineid_buf));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* hash to get seed */
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek seed = string_hash_func(seed_str);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering srandom(seed);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for(i = 0; i < ETH_ALEN; i++) {
943aad8ca57a6b5c49c4ea60f9e8c13bf9b20e6cZbigniew Jędrzejewski-Szmek mac->ether_addr_octet[i] = random();
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek }
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* see eth_random_addr in the kernel */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *name;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *new_name = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ether_addr generated_mac;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ether_addr *mac = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r, ifindex;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name = udev_device_get_sysname(device);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!name)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EINVAL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Configuring %s", name);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (config->description) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = udev_device_set_sysattr_value(device, "ifalias",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering config->description);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Could not set description of %s to '%s': %s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name, config->description, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
4ec24515daa780118709e04cd78dae93f25a8428Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = ethtool_set_speed(ctx->ethtool_fd, name, config->speed, config->duplex);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Could not set speed or duplex of %s to %u Mbytes (%s): %s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name, config->speed, duplex_to_string(config->duplex), strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = ethtool_set_wol(ctx->ethtool_fd, name, config->wol);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Could not set WakeOnLan of %s to %s: %s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name, wol_to_string(config->wol), strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifindex = udev_device_get_ifindex(device);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (ifindex <= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Could not find ifindex");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENODEV;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (config->name_policy && enable_name_policy()) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering NamePolicy *policy;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering switch (*policy) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering case NAMEPOLICY_ONBOARD:
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering case NAMEPOLICY_SLOT:
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering case NAMEPOLICY_PATH:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering case NAMEPOLICY_MAC:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering default:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!new_name && config->name) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering new_name = config->name;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering switch (config->mac_policy) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering case MACPOLICY_PERSISTENT:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!mac_is_permanent(device)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = get_mac(device, false, &generated_mac);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mac = &generated_mac;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering case MACPOLICY_RANDOM:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!mac_is_random(device)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = get_mac(device, true, &generated_mac);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mac = &generated_mac;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering default:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mac = config->mac;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = rtnl_set_properties(ctx->rtnl, ifindex, new_name, mac, config->mtu);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Could not set Name, MACAddress or MTU on %s: %s", name, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering