diff options
author | Sam Leonard <sam.leonard@codethink.co.uk> | 2024-04-12 16:46:04 +0200 |
---|---|---|
committer | Sam Leonard <sam.leonard@codethink.co.uk> | 2024-04-15 12:42:06 +0200 |
commit | c3dd4e20fe5d070dec6e789109ef6bdd41796ec3 (patch) | |
tree | 2e60f604fcc47344e0d06142301b226244bf68c0 /src/vmspawn | |
parent | nspawn,shared/netif-util: move generate_mac and shorten_ifname to shared/neti... (diff) | |
download | systemd-c3dd4e20fe5d070dec6e789109ef6bdd41796ec3.tar.xz systemd-c3dd4e20fe5d070dec6e789109ef6bdd41796ec3.zip |
vmspawn: generate predicatable TAP device names and MAC addresses
Diffstat (limited to 'src/vmspawn')
-rw-r--r-- | src/vmspawn/vmspawn.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index fea154ae1f..0eba456971 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <net/if.h> +#include <linux/if.h> #include <getopt.h> #include <stdint.h> #include <stdio.h> @@ -24,6 +26,7 @@ #include "discover-image.h" #include "dissect-image.h" #include "escape.h" +#include "ether-addr-util.h" #include "event-util.h" #include "extract-word.h" #include "fd-util.h" @@ -40,6 +43,7 @@ #include "macro.h" #include "main-func.h" #include "mkdir.h" +#include "netif-util.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -65,6 +69,8 @@ #include "vmspawn-settings.h" #include "vmspawn-util.h" +#define VM_TAP_HASH_KEY SD_ID128_MAKE(01,d0,c6,4c,2b,df,24,fb,c0,f8,b2,09,7d,59,b2,93) + static bool arg_quiet = false; static PagerFlags arg_pager_flags = 0; static char *arg_directory = NULL; @@ -98,6 +104,7 @@ static char *arg_background = NULL; static bool arg_pass_ssh_key = true; static char *arg_ssh_key_type = NULL; static bool arg_discard_disk = true; +struct ether_addr arg_network_provided_mac = {}; STATIC_DESTRUCTOR_REGISTER(arg_directory, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -188,6 +195,20 @@ static int help(void) { return 0; } +static int parse_environment(void) { + const char *e; + int r; + + e = getenv("SYSTEMD_VMSPAWN_NETWORK_MAC"); + if (e) { + r = parse_ether_addr(e, &arg_network_provided_mac); + if (r < 0) + return log_error_errno(r, "Failed to parse provided MAC address via environment variable"); + } + + return 0; +} + static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, @@ -1287,9 +1308,31 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { } } - if (arg_network_stack == NETWORK_STACK_TAP) - r = strv_extend_many(&cmdline, "-nic", "tap,script=no,model=virtio-net-pci"); - else if (arg_network_stack == NETWORK_STACK_USER) + if (arg_network_stack == NETWORK_STACK_TAP) { + _cleanup_free_ char *tap_name = NULL; + struct ether_addr mac_vm = {}; + + tap_name = strjoin("tp-", arg_machine); + if (!tap_name) + return log_oom(); + + (void) net_shorten_ifname(tap_name, /* check_naming_scheme= */ false); + + if (ether_addr_is_null(&arg_network_provided_mac)){ + r = net_generate_mac(arg_machine, &mac_vm, VM_TAP_HASH_KEY, 0); + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for VM side: %m"); + } else + mac_vm = arg_network_provided_mac; + + r = strv_extend(&cmdline, "-nic"); + if (r < 0) + return log_oom(); + + r = strv_extendf(&cmdline, "tap,ifname=%s,script=no,model=virtio-net-pci,mac=%s", tap_name, ETHER_ADDR_TO_STR(&mac_vm)); + if (r < 0) + return log_oom(); + } else if (arg_network_stack == NETWORK_STACK_USER) r = strv_extend_many(&cmdline, "-nic", "user,model=virtio-net-pci"); else r = strv_extend_many(&cmdline, "-nic", "none"); @@ -2014,6 +2057,10 @@ static int run(int argc, char *argv[]) { /* don't attempt to register as a machine when running as a user */ arg_register = arg_privileged; + r = parse_environment(); + if (r < 0) + return r; + r = parse_argv(argc, argv); if (r <= 0) return r; |