link-config.c revision f8a0bb5285024b6ce372c3157e761e6543ebdcd2
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmekstatic const char* const link_dirs[] = {
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom GundersenDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint link_config_ctx_new(link_config_ctx **ret) {
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
977085794d2996320e345433403de75f662b0622Tom Gundersenstatic int link_config_ctx_connect(link_config_ctx *ctx) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic void link_configs_free(link_config_ctx *ctx) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenvoid link_config_ctx_free(link_config_ctx *ctx) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int load_link(link_config_ctx *ctx, const char *filename) {
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek _cleanup_free_ link_config *link = NULL;
6e37cd2f4af8928d905203108a4331e375d7127cThomas Hindoe Paaboel Andersen _cleanup_fclose_ FILE *file = NULL;
6916ec29afd488d91e7e0fcbcc2e006b4e5f28dfTom Gundersen log_debug("skipping empty file: %s", filename);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (void*) link_config_gperf_lookup, false, false, link);
489124365d1d391864898b9869dd668eea5b2e28Dave Reisner log_warning("Could not parse config file %s: %s", filename, strerror(-r));
98a375f6d5cac24eb80d6d4e00699851324afdecTom Gundersen log_debug("Parsed configuration file %s", filename);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersenstatic bool enable_name_policy(void) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return false;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_info("Network interface NamePolicy= disabled on kernel commandline, ignoring.");
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen /* update timestamp */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen log_error("failed to enumerate link files: %s", strerror(-r));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenbool link_config_should_reload(link_config_ctx *ctx) {
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) {
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen if (net_match_config(link->match_mac, link->match_path, link->match_driver,
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen link->match_virt, link->match_kernel, link->match_arch,
505f8da7325591defe5f751f328bd26915267602Tom Gundersen ether_aton(udev_device_get_sysattr_value(device, "address")),
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen udev_device_get_property_value(device, "ID_PATH"),
9b1c2626cef16722603bded9bb52033aba34dd74Tom Gundersen udev_device_get_driver(udev_device_get_parent(device)),
bf175aafd20c9ef974709ef12c5acf836121af33Tom Gundersen udev_device_get_property_value(device, "ID_NET_DRIVER"),
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen log_debug("Config file %s applies to device %s",
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic bool mac_is_random(struct udev_device *device) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen const char *s;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen s = udev_device_get_sysattr_value(device, "addr_assign_type");
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen return false; /* if we don't know, assume it is not random */
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen return false;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen /* check for NET_ADDR_RANDOM */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersenstatic int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering random_bytes(mac->ether_addr_octet, ETH_ALEN);
b5db00e52ee2e20578839e4e4488f7b9af9abc38Umut Tezduyar Lindskog r = net_get_unique_predictable_data(device, result);
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering memcpy(mac->ether_addr_octet, result, ETH_ALEN);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen /* see eth_random_addr in the kernel */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersenint link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) {
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen r = ethtool_set_speed(ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex);
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
733f7a2c69c794a81978a08a79916c224ba355a6Tom Gundersen old_name, config->speed / 1024, duplex_to_string(config->duplex),
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = ethtool_set_wol(ctx->ethtool_fd, old_name, config->wol);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_warning("Could not set WakeOnLan of %s to %s: %s",
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen old_name, wol_to_string(config->wol), strerror(-r));
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (ctx->enable_name_policy && config->name_policy) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen *name = new_name; /* a name was set by a policy */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen *name = config->name; /* a name was set manually in the config */
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen r = rtnl_set_link_properties(ctx->rtnl, ifindex, config->alias, mac, config->mtu);
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen log_warning("Could not set Alias, MACAddress or MTU on %s: %s", old_name, strerror(-r));
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenint link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen r = ethtool_get_driver(ctx->ethtool_fd, name, &driver);
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mackstatic const char* const mac_policy_table[_MACPOLICY_MAX] = {
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mackstatic const char* const name_policy_table[_NAMEPOLICY_MAX] = {
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
be32eb9b7fbcb22e4b648086d644135e38279633Tom GundersenDEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy");