link-config.c revision 2a73e0d39a9bec82c3800071e375d27164727e71
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering/***
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering This file is part of systemd.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering systemd is free software; you can redistribute it and/or modify it
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering under the terms of the GNU Lesser General Public License as published by
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering (at your option) any later version.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering systemd is distributed in the hope that it will be useful, but
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering Lesser General Public License for more details.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering You should have received a copy of the GNU Lesser General Public License
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering***/
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include <netinet/ether.h>
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include <net/if.h>
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "link-config.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "ethtool-util.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "libudev-private.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "sd-rtnl.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "util.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "log.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "strv.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "path-util.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "conf-parser.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "conf-files.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringstruct link_config_ctx {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering LIST_HEAD(link_config, links);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering int ethtool_fd;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering sd_rtnl *rtnl;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering char **link_dirs;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering usec_t *link_dirs_ts_usec;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering};
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_config_ctx *ctx;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering int r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering if (!ret)
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering return -EINVAL;
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering ctx = new0(link_config_ctx, 1);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!ctx)
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return -ENOMEM;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = ethtool_connect(&ctx->ethtool_fd);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (r < 0) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_config_ctx_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = sd_rtnl_open(0, &ctx->rtnl);
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering if (r < 0) {
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering link_config_ctx_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering LIST_HEAD_INIT(ctx->links);
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering ctx->link_dirs = strv_new("/etc/net/links",
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering "/run/net/links",
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering "/usr/lib/net/links",
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering NULL);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!ctx->link_dirs) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_error("failed to build link config directory array");
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_config_ctx_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return -ENOMEM;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!path_strv_canonicalize_uniq(ctx->link_dirs)) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering log_error("failed to canonicalize link config directories\n");
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering link_config_ctx_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return -ENOMEM;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering ctx->link_dirs_ts_usec = calloc(strv_length(ctx->link_dirs), sizeof(usec_t));
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if(!ctx->link_dirs_ts_usec) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_config_ctx_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return -ENOMEM;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering *ret = ctx;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering}
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_config *link, *link_next;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!ctx)
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering return;
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering free(link->filename);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering free(link->match_path);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering free(link->match_driver);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering free(link->match_type);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering free(link->description);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering free(link);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering}
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering if (!ctx)
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering return;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering if (ctx->ethtool_fd >= 0)
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering close_nointr_nofail(ctx->ethtool_fd);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering sd_rtnl_unref(ctx->rtnl);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering strv_free(ctx->link_dirs);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering free(ctx->link_dirs_ts_usec);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_configs_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return;
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering}
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering link_config *link;
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering FILE *file;
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering int r;
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering file = fopen(filename, "re");
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering if (!file) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (errno == ENOENT)
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering else
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return errno;
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link = new0(link_config, 1);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!link) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = log_oom();
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering goto failure;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering (void*) link_config_gperf_lookup, false, false, link);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (r < 0) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_warning("Colud not parse config file %s: %s", filename, strerror(-r));
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering goto failure;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering } else
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_info("Parsed configuration file %s", filename);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link->filename = strdup(filename);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering LIST_PREPEND(links, ctx->links, link);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringfailure:
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering free(link);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering}
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering int r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering char **files, **f;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_configs_free(ctx);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* update timestamps */
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering paths_check_timestamp(ctx->link_dirs, ctx->link_dirs_ts_usec, true);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, (const char **)ctx->link_dirs);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (r < 0) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_error("failed to enumerate link files: %s", strerror(-r));
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = load_link(ctx, *f);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (r < 0)
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering}
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringbool link_config_should_reload(link_config_ctx *ctx) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return paths_check_timestamp(ctx->link_dirs, ctx->link_dirs_ts_usec, false);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering}
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringstatic bool match_config(link_config *match, struct udev_device *device) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering const char *property;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (match->match_mac) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering property = udev_device_get_sysattr_value(device, "address");
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!property || !streq(match->match_mac, property)) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_debug("Device MAC address (%s) did not match MACAddress=%s", property, match->match_mac);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (match->match_path) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering property = udev_device_get_property_value(device, "ID_PATH");
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!property || !streq(match->match_path, property)) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_debug("Device's persistent path (%s) did not match Path=%s", property, match->match_path);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (match->match_driver) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering property = udev_device_get_driver(device);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!property || !streq(match->match_driver, property)) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_debug("Device driver (%s) did not match Driver=%s", property, match->match_driver);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (match->match_type) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering property = udev_device_get_devtype(device);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!property || !streq(match->match_type, property)) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering log_debug("Device type (%s) did not match Type=%s", property, match->match_type);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return 0;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 1;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering}
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering link_config *link;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering LIST_FOREACH(links, link, ctx->links) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (!match_config(link, device)) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_info("Config file %s does not apply to device %s", link->filename, udev_device_get_sysname(device));
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering } else {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering log_info("Config file %s applies to device %s", link->filename, udev_device_get_sysname(device));
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering *ret = link;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return 0;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return -ENOENT;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering}
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringstatic int rtnl_set_properties(sd_rtnl *rtnl, int ifindex, const char *name, const char *mac, unsigned int mtu) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering char new_name[IFNAMSIZ];
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering struct ether_addr new_mac;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering bool need_update;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering int r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering assert(rtnl);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(ifindex > 0);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = sd_rtnl_message_link_new(RTM_NEWLINK, ifindex, 0, 0, &message);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (r < 0)
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (name) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering strscpy(new_name, IFNAMSIZ, name);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = sd_rtnl_message_append(message, IFLA_IFNAME, new_name);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (r < 0)
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering return r;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering
need_update = true;
}
if (mac) {
r = sscanf(mac, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
&new_mac.ether_addr_octet[0],
&new_mac.ether_addr_octet[1],
&new_mac.ether_addr_octet[2],
&new_mac.ether_addr_octet[3],
&new_mac.ether_addr_octet[4],
&new_mac.ether_addr_octet[5]);
if (r != 6)
return -EINVAL;
r = sd_rtnl_message_append(message, IFLA_ADDRESS, &new_mac);
if (r < 0)
return r;
need_update = true;
}
if (mtu > 0) {
r = sd_rtnl_message_append(message, IFLA_MTU, &mtu);
if (r < 0)
return r;
need_update = true;
}
if (need_update) {
r = sd_rtnl_send_with_reply_and_block(rtnl, message, 250 * USEC_PER_MSEC, NULL);
if (r < 0)
return r;
}
return 0;
}
int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device) {
const char *name;
int r, ifindex;
name = udev_device_get_sysname(device);
if (!name)
return -EINVAL;
log_info("Configuring %s", name);
if (config->description) {
r = udev_device_set_sysattr_value(device, "ifalias",
config->description);
if (r < 0)
log_warning("Could not set description of %s to '%s': %s",
name, config->description, strerror(-r));
else
log_info("Set link description of %s to '%s'", name,
config->description);
}
if (config->speed || config->duplex) {
r = ethtool_set_speed(ctx->ethtool_fd, name,
config->speed, config->duplex);
if (r < 0)
log_warning("Could not set speed or duplex of %s to %u Mbytes (%s): %s",
name, config->speed, config->duplex, strerror(-r));
else
log_info("Set speed or duplex of %s to %u Mbytes (%s)", name,
config->speed, config->duplex);
}
if (config->wol) {
r = ethtool_set_wol(ctx->ethtool_fd, name, config->wol);
if (r < 0)
log_warning("Could not set WakeOnLan of %s to %s: %s",
name, config->wol, strerror(-r));
else
log_info("Set WakeOnLan of %s to %s", name, config->wol);
}
ifindex = udev_device_get_ifindex(device);
if (ifindex <= 0) {
log_warning("Could not find ifindex");
return -ENODEV;
}
r = rtnl_set_properties(ctx->rtnl, ifindex, config->name, config->mac, config->mtu);
if (r < 0) {
log_warning("Could not set Name, MACAddress or MTU on %s", name);
return r;
}
return 0;
}