link-config.c revision edf029b7fd9a5853a87d3ca99aac2922bb8a277e
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/>.
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic const char* const link_dirs[] = {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic int link_config_ctx_connect(link_config_ctx *ctx) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic void link_configs_free(link_config_ctx *ctx) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringvoid link_config_ctx_free(link_config_ctx *ctx) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering log_debug("skipping empty file: %s", filename);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering (void*) link_config_gperf_lookup, false, false, link);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering log_warning("Could not parse config file %s: %s", filename, strerror(-r));
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering log_debug("Parsed configuration file %s", filename);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic bool enable_name_policy(void) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek ctx->enable_name_policy = false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* update timestamp */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering log_error("failed to enumerate link files: %s", strerror(-r));
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringbool link_config_should_reload(link_config_ctx *ctx) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (net_match_config(link->match_mac, link->match_path, link->match_driver,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link->match_type, NULL, link->match_host,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering link->match_virt, link->match_kernel, link->match_arch,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ether_aton(udev_device_get_sysattr_value(device, "address")),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_property_value(device, "ID_PATH"),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_driver(udev_device_get_parent(device)),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering udev_device_get_property_value(device, "ID_NET_DRIVER"),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug("Config file %s applies to device %s",
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringstatic bool mac_is_random(struct udev_device *device) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s = udev_device_get_sysattr_value(device, "addr_assign_type");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return false; /* if we don't know, assume it is not random */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* check for NET_ADDR_RANDOM */
7f0d207d2c816e0a8cb2742b0a789911f7c99356Lennart Poetteringstatic int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = net_get_unique_predictable_data(device, result);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* see eth_random_addr in the kernel */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering old_name = udev_device_get_sysname(device);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering old_name, config->speed / 1024, duplex_to_string(config->duplex),
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering log_warning("Could not set WakeOnLan of %s to %s: %s",
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering old_name, wol_to_string(config->wol), strerror(-r));
554604b3073467af75dc94fac9e2343148603289Lennart Poettering ifindex = udev_device_get_ifindex(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ctx->enable_name_policy && config->name_policy) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering *name = new_name; /* a name was set by a policy */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering *name = config->name; /* a name was set manually in the config */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = get_mac(device, false, &generated_mac);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = get_mac(device, true, &generated_mac);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek r = link_config_ctx_connect(ctx);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = ethtool_get_driver(ctx->ethtool_fd, name, &driver);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic const char* const mac_policy_table[_MACPOLICY_MAX] = {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic const char* const name_policy_table[_NAMEPOLICY_MAX] = {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart PoetteringDEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");