link-config.c revision 9a4b012e43f23516373bf398dd9a458439d19939
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/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char* const link_dirs[] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void link_config_free(link_config *link) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
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 PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_ctx_new(link_config_ctx **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int load_link(link_config_ctx *ctx, const char *filename) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(link_config_freep) link_config *link = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Skipping empty file: %s", filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "Match\0Link\0Ethernet\0",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering config_item_perf_lookup, link_config_gperf_lookup,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering false, false, true, link);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Parsed configuration file %s", filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool enable_name_policy(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering FOREACH_WORD_QUOTED(word, l, line, state)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_load(link_config_ctx *ctx) {
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering /* update timestamp */
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering return log_error_errno(r, "failed to enumerate link files: %m");
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 attr_value = udev_device_get_sysattr_value(device, "address");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (net_match_config(link->match_mac, link->match_path, link->match_driver,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->match_type, link->match_name, link->match_host,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->match_virt, link->match_kernel, link->match_arch,
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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)),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering udev_device_get_property_value(device, "ID_NET_DRIVER"),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned char name_assign_type = NET_NAME_UNKNOWN;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (void)safe_atou8(attr_value, &name_assign_type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename, udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (name_assign_type == NET_NAME_RENAMED) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename, udev_device_get_sysname(device));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Config file %s applies to device %s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link->filename, udev_device_get_sysname(device));
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");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* these were already named by userspace, do not touch again */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* the kernel claims to have given a predictable name */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* fall through */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* the name is known to be bad, or of an unknown type */
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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) */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint link_config_apply(link_config_ctx *ctx, link_config *config,
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ifindex = udev_device_get_ifindex(device);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ctx->enable_name_policy && config->name_policy) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !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");
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;