From e9b7408eb90918aace3b8153a8db1ca49dbb64f6 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Fri, 17 Nov 2023 20:37:26 +0800 Subject: [PATCH 1/3] networkctl: use RET_GATHER more --- src/network/networkctl.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index ec31e8eb44..d69d37fcd1 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -2741,23 +2741,25 @@ static int link_renew_one(sd_bus *bus, int index, const char *name) { static int link_renew(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - int index, k = 0, r; + int r; r = acquire_bus(&bus); if (r < 0) return r; + r = 0; + for (int i = 1; i < argc; i++) { + int index; + index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); if (index < 0) return index; - r = link_renew_one(bus, index, argv[i]); - if (r < 0 && k >= 0) - k = r; + RET_GATHER(r, link_renew_one(bus, index, argv[i])); } - return k; + return r; } static int link_force_renew_one(sd_bus *bus, int index, const char *name) { @@ -3281,23 +3283,22 @@ static int verb_cat(int argc, char *argv[], void *userdata) { if (link_config) { r = get_config_files_by_link_config(link_config, &rtnl, &path, &dropins, /* ret_reload = */ NULL); if (r < 0) - return ret < 0 ? ret : r; + return RET_GATHER(ret, r); } else { r = get_config_files_by_name(*name, &path, &dropins); if (r == -ENOENT) { - log_error_errno(r, "Cannot find network config file '%s'.", *name); - ret = ret < 0 ? ret : r; + RET_GATHER(ret, log_error_errno(r, "Cannot find network config file '%s'.", *name)); continue; } if (r < 0) { log_error_errno(r, "Failed to get the path of network config '%s': %m", *name); - return ret < 0 ? ret : r; + return RET_GATHER(ret, r); } } r = cat_files(path, dropins, /* flags = */ CAT_FORMAT_HAS_SECTIONS); if (r < 0) - return ret < 0 ? ret : r; + return RET_GATHER(ret, r); } return ret; From 7050f7419b6bc829706ba858e8eea1b10334dba8 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 21 Nov 2023 21:21:14 +0800 Subject: [PATCH 2/3] networkctl: drop one assertion If there're no existing drop-ins, the assertions are unnecessarily triggered. --- src/network/networkctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index d69d37fcd1..123ae62514 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -2909,7 +2909,6 @@ static int get_dropin_by_name( char **ret) { assert(name); - assert(dropins); assert(ret); STRV_FOREACH(i, dropins) @@ -3076,7 +3075,6 @@ static int add_config_to_edit( assert(context); assert(path); - assert(!arg_drop_in || dropins); if (path_startswith(path, "/usr")) { _cleanup_free_ char *name = NULL; From 2b98926f9809eb858a5abe4f64ebd067df5059d5 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Fri, 17 Nov 2023 22:08:28 +0800 Subject: [PATCH 3/3] networkctl: introduce --runtime for editing network config under /run/ --- man/networkctl.xml | 14 +++++++++- src/network/networkctl.c | 39 ++++++++++++++++++++++----- test/units/testsuite-74.networkctl.sh | 12 +++++++-- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/man/networkctl.xml b/man/networkctl.xml index 68b1d97f09..3a2dc09ecc 100644 --- a/man/networkctl.xml +++ b/man/networkctl.xml @@ -430,7 +430,8 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) Edit network configuration files, which include .network, .netdev, and .link files. If no network config file - matching the given name is found, a new one will be created under /etc/. + matching the given name is found, a new one will be created under /etc/ or + /run/, depending on whether is specified. Specially, if the name is prefixed by @, it will be treated as a network interface, and editing will be performed on the network config files associated with it. Additionally, the interface name can be suffixed with :network (default) @@ -541,6 +542,17 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) + + + + + + When used with edit, edit the file under /run/ + instead of /etc/. + + + + diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 123ae62514..939b590a6d 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -87,6 +87,7 @@ static bool arg_no_reload = false; static bool arg_all = false; static bool arg_stats = false; static bool arg_full = false; +static bool arg_runtime = false; static unsigned arg_lines = 10; static char *arg_drop_in = NULL; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; @@ -3076,14 +3077,20 @@ static int add_config_to_edit( assert(context); assert(path); - if (path_startswith(path, "/usr")) { + /* If we're supposed to edit main config file in /run/, but a config with the same name is present + * under /etc/, we bail out since the one in /etc/ always overrides that in /run/. */ + if (arg_runtime && !arg_drop_in && path_startswith(path, "/etc")) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "Cannot edit runtime config file: overriden by %s", path); + + if (path_startswith(path, "/usr") || arg_runtime != !!path_startswith(path, "/run")) { _cleanup_free_ char *name = NULL; r = path_extract_filename(path, &name); if (r < 0) return log_error_errno(r, "Failed to extract filename from '%s': %m", path); - new_path = path_join(NETWORK_DIRS[0], name); + new_path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], name); if (!new_path) return log_oom(); } @@ -3091,16 +3098,27 @@ static int add_config_to_edit( if (!arg_drop_in) return edit_files_add(context, new_path ?: path, path, NULL); + bool need_new_dropin; + r = get_dropin_by_name(arg_drop_in, dropins, &old_dropin); if (r < 0) return log_error_errno(r, "Failed to acquire drop-in '%s': %m", arg_drop_in); + if (r > 0) { + /* See the explanation above */ + if (arg_runtime && path_startswith(old_dropin, "/etc")) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "Cannot edit runtime config file: overriden by %s", old_dropin); - if (r > 0 && !path_startswith(old_dropin, "/usr")) - /* An existing drop-in is found and not in /usr/. Let's edit it directly. */ + need_new_dropin = path_startswith(old_dropin, "/usr") || arg_runtime != !!path_startswith(old_dropin, "/run"); + } else + need_new_dropin = true; + + if (!need_new_dropin) + /* An existing drop-in is found in the correct scope. Let's edit it directly. */ dropin_path = TAKE_PTR(old_dropin); else { - /* No drop-in was found or an existing drop-in resides in /usr/. Let's create - * a new drop-in file. */ + /* No drop-in was found or an existing drop-in is in a different scope. Let's create a new + * drop-in file. */ dropin_path = strjoin(new_path ?: path, ".d/", arg_drop_in); if (!dropin_path) return log_oom(); @@ -3209,7 +3227,7 @@ static int verb_edit(int argc, char *argv[], void *userdata) { log_debug("No existing network config '%s' found, creating a new file.", *name); - path = path_join(NETWORK_DIRS[0], *name); + path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], *name); if (!path) return log_oom(); @@ -3340,6 +3358,7 @@ static int help(void) { " --no-reload Do not reload systemd-networkd or systemd-udevd\n" " after editing network config\n" " --drop-in=NAME Edit specified drop-in instead of main config file\n" + " --runtime Edit runtime config files\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -3357,6 +3376,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_JSON, ARG_NO_RELOAD, ARG_DROP_IN, + ARG_RUNTIME, }; static const struct option options[] = { @@ -3371,6 +3391,7 @@ static int parse_argv(int argc, char *argv[]) { { "json", required_argument, NULL, ARG_JSON }, { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, { "drop-in", required_argument, NULL, ARG_DROP_IN }, + { "runtime", no_argument, NULL, ARG_RUNTIME }, {} }; @@ -3401,6 +3422,10 @@ static int parse_argv(int argc, char *argv[]) { arg_no_reload = true; break; + case ARG_RUNTIME: + arg_runtime = true; + break; + case ARG_DROP_IN: if (isempty(optarg)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name."); diff --git a/test/units/testsuite-74.networkctl.sh b/test/units/testsuite-74.networkctl.sh index 0a687af6e4..b857abcf9a 100755 --- a/test/units/testsuite-74.networkctl.sh +++ b/test/units/testsuite-74.networkctl.sh @@ -11,7 +11,7 @@ at_exit() { systemctl stop systemd-networkd if [[ -v NETWORK_NAME && -v NETDEV_NAME && -v LINK_NAME ]]; then - rm -fvr {/usr/lib,/etc}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \ + rm -fvr {/usr/lib,/etc,/run}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \ {/usr/lib,/etc}/systemd/network/"$LINK_NAME" "/etc/systemd/network/${NETWORK_NAME}.d" \ "new" "+4" fi @@ -35,9 +35,14 @@ cat >new <"+4" <