]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: allow user-specified MAC address on container side
authorRaul Cheleguini <raul.cheleguini@gmail.com>
Wed, 4 Oct 2023 02:06:38 +0000 (23:06 -0300)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 25 Oct 2023 12:59:46 +0000 (13:59 +0100)
Introduce the environment variable SYSTEMD_NSPAWN_NETWORK_MAC to allow
user-specified MAC address on container side.

docs/ENVIRONMENT.md
src/nspawn/nspawn-network.c
src/nspawn/nspawn-network.h
src/nspawn/nspawn.c

index 9ebf2b3c64daf11298758dbd15390b98ef331934..5747c103e2b0c149924d70af36567f9ad8107b96 100644 (file)
@@ -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
index b83e472245c9308f4a2a099a024c217c2ed035d9..853f4608d3fb21ee2fbf79ad6c69daccdc33d603 100644 (file)
@@ -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)
index 355d813c963d28f64ae7950a3764f45ab60d095f..8e37d15ad2758585a6f4c4031e1161c7aa233873 100644 (file)
@@ -5,9 +5,11 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
+#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);
index de76b88c2788392082b850cab1e6c7eaf47b91ff..f1bb8796443eb1ffa30f527d4450e51ccfd71520 100644 (file)
@@ -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)