link-config.c revision 58c9846d32e55799b6e4607136a34e2727c919ac
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
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 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 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/>.
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic const char* const link_dirs[] = {
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 Poetteringint link_config_ctx_new(link_config_ctx **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_debug("Skipping empty file: %s", filename);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "Match\0Link\0Ethernet\0",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering config_item_perf_lookup, link_config_gperf_lookup,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering false, false, true, link);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug("Parsed configuration file %s", filename);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic bool enable_name_policy(void) {
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering FOREACH_WORD_QUOTED(word, l, line, state)
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poetteringint link_config_load(link_config_ctx *ctx) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* update timestamp */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_error("failed to enumerate link files: %s", strerror(-r));
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 Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char* attr_value = udev_device_get_sysattr_value(device, "address");
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 log_debug("Config file %s applies to device %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
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 Poetteringstatic bool should_rename(struct udev_device *device, bool respect_predictable) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
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");
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* these were already named by userspace, do not touch again */
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* the kernel claims to have given a predictable name */
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* fall through */
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering /* the name is known to be bad, or of an unknown type */
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = net_get_unique_predictable_data(device, result);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
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) */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering struct udev_device *device, const char **name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name = udev_device_get_sysname(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering duplex_to_string(config->duplex), strerror(-r));
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
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 ifindex = udev_device_get_ifindex(device);
return -ENODEV;
switch (*policy) {
case NAMEPOLICY_KERNEL:
respect_predictable = true;
case NAMEPOLICY_DATABASE:
case NAMEPOLICY_ONBOARD:
case NAMEPOLICY_SLOT:
case NAMEPOLICY_PATH:
case NAMEPOLICY_MAC:
if (!new_name)
case MACPOLICY_PERSISTENT:
if (r == -ENOENT)
case MACPOLICY_RANDOM:
if (r == -ENOENT)
const char *name;
char *driver;
if (!name)
return -EINVAL;