From: Raul Cheleguini Date: Wed, 4 Oct 2023 02:06:38 +0000 (-0300) Subject: nspawn: allow user-specified MAC address on container side X-Git-Tag: v255-rc1~142 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=813dbff4d59a4f256f8824c45af9e8af8f7b4c05;p=thirdparty%2Fsystemd.git nspawn: allow user-specified MAC address on container side Introduce the environment variable SYSTEMD_NSPAWN_NETWORK_MAC to allow user-specified MAC address on container side. --- diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 9ebf2b3c64d..5747c103e2b 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -170,6 +170,12 @@ All tools: friends. This is equivalent to passing `--suppress-sync=yes` on the `systemd-nspawn` command line. +* `$SYSTEMD_NSPAWN_NETWORK_MAC=...` — if set, allows users to set a specific MAC + address for a container, ensuring that it uses the provided value instead of + generating a random one. It is effective when used with `--network-veth`. The + expected format is six groups of two hexadecimal digits separated by colons, + e.g. `SYSTEMD_NSPAWN_NETWORK_MAC=12:34:56:78:90:AB` + `systemd-logind`: * `$SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1` — if set, report that diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index b83e472245c..853f4608d3f 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -236,7 +236,8 @@ static int shorten_ifname(char *ifname) { int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], - bool bridge) { + bool bridge, + struct ether_addr *provided_mac) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; struct ether_addr mac_host, mac_container; @@ -255,9 +256,12 @@ int setup_veth(const char *machine_name, if (r > 0) a = strjoina(bridge ? "vb-" : "ve-", machine_name); - r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0); - if (r < 0) - return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m"); + if (ether_addr_is_null(provided_mac)){ + r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0); + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m"); + } else + mac_container = *provided_mac; r = generate_mac(machine_name, &mac_host, HOST_HASH_KEY, 0); if (r < 0) diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h index 355d813c963..8e37d15ad27 100644 --- a/src/nspawn/nspawn-network.h +++ b/src/nspawn/nspawn-network.h @@ -5,9 +5,11 @@ #include #include +#include "ether-addr-util.h" + int test_network_interfaces_initialized(char **iface_pairs); -int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge); +int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge, struct ether_addr *provided_mac); int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs); int setup_bridge(const char *veth_name, const char *bridge_name, bool create); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index de76b88c278..f1bb8796443 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -24,6 +24,7 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "ether-addr-util.h" #include "barrier.h" #include "base-filesystem.h" #include "blkid-util.h" @@ -188,6 +189,7 @@ static char **arg_network_veth_extra = NULL; static char *arg_network_bridge = NULL; static char *arg_network_zone = NULL; static char *arg_network_namespace_path = NULL; +struct ether_addr arg_network_provided_mac = {}; static PagerFlags arg_pager_flags = 0; static unsigned long arg_personality = PERSONALITY_INVALID; static char *arg_image = NULL; @@ -668,6 +670,13 @@ static int parse_environment(void) { if (e) arg_container_service_name = e; + e = getenv("SYSTEMD_NSPAWN_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"); + } + r = getenv_bool("SYSTEMD_SUPPRESS_SYNC"); if (r >= 0) arg_suppress_sync = r; @@ -4978,7 +4987,7 @@ static int run_container( if (arg_network_veth) { r = setup_veth(arg_machine, *pid, veth_name, - arg_network_bridge || arg_network_zone); + arg_network_bridge || arg_network_zone, &arg_network_provided_mac); if (r < 0) return r; else if (r > 0)