networkctl: introduce verb mask and unmask

Suggested in https://github.com/systemd/systemd/pull/29928#discussion_r1386626565
This commit is contained in:
Mike Yuan
2023-12-20 12:46:46 +08:00
parent 7ce6a0960f
commit 28bb29cbb4
5 changed files with 172 additions and 4 deletions
+108
View File
@@ -13,6 +13,7 @@
#include "bus-wait-for-jobs.h"
#include "conf-files.h"
#include "edit-util.h"
#include "mkdir-label.h"
#include "netlink-util.h"
#include "networkctl.h"
#include "networkctl-config-file.h"
@@ -518,3 +519,110 @@ int verb_cat(int argc, char *argv[], void *userdata) {
return ret;
}
int verb_mask(int argc, char *argv[], void *userdata) {
ReloadFlags flags = 0;
int r;
r = mac_selinux_init();
if (r < 0)
return r;
STRV_FOREACH(name, strv_skip(argv, 1)) {
_cleanup_free_ char *config_path = NULL, *symlink_path = NULL;
ReloadFlags reload;
/* We update the real 'flags' at last, since the operation can be skipped. */
if (ENDSWITH_SET(*name, ".network", ".netdev"))
reload = RELOAD_NETWORKD;
else if (endswith(*name, ".link"))
reload = RELOAD_UDEVD;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid network config name '%s'.", *name);
r = get_config_files_by_name(*name, /* allow_masked = */ true, &config_path, /* ret_dropins = */ NULL);
if (r == -ENOENT)
log_warning("No existing network config '%s' found, proceeding anyway.", *name);
else if (r < 0)
return log_error_errno(r, "Failed to get the path of network config '%s': %m", *name);
else if (!path_startswith(config_path, "/usr")) {
r = null_or_empty_path(config_path);
if (r < 0)
return log_error_errno(r,
"Failed to check if '%s' is masked: %m", config_path);
if (r > 0) {
log_debug("%s is already masked, skipping.", config_path);
continue;
}
/* At this point, we have found a config under mutable dir (/run/ or /etc/),
* so masking through /run/ (--runtime) is not possible. If it's under /etc/,
* then it doesn't work without --runtime either. */
if (arg_runtime || path_startswith(config_path, "/etc"))
return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
"Cannot mask network config %s: %s exists",
*name, config_path);
}
symlink_path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], *name);
if (!symlink_path)
return log_oom();
(void) mkdir_parents_label(symlink_path, 0755);
if (symlink("/dev/null", symlink_path) < 0)
return log_error_errno(errno,
"Failed to create symlink '%s' to /dev/null: %m", symlink_path);
flags |= reload;
log_info("Successfully created symlink '%s' to /dev/null.", symlink_path);
}
return reload_daemons(flags);
}
int verb_unmask(int argc, char *argv[], void *userdata) {
ReloadFlags flags = 0;
int r;
STRV_FOREACH(name, strv_skip(argv, 1)) {
_cleanup_free_ char *path = NULL;
ReloadFlags reload;
if (ENDSWITH_SET(*name, ".network", ".netdev"))
reload = RELOAD_NETWORKD;
else if (endswith(*name, ".link"))
reload = RELOAD_UDEVD;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid network config name '%s'.", *name);
r = get_config_files_by_name(*name, /* allow_masked = */ true, &path, /* ret_dropins = */ NULL);
if (r == -ENOENT) {
log_debug_errno(r, "Network configuration '%s' doesn't exist, skipping.", *name);
continue;
}
if (r < 0)
return log_error_errno(r, "Failed to get the path of network config '%s': %m", *name);
r = null_or_empty_path(path);
if (r < 0)
return log_error_errno(r, "Failed to check if '%s' is masked: %m", path);
if (r == 0)
continue;
if (path_startswith(path, "/usr"))
return log_error_errno(r, "Cannot unmask network config under /usr/: %s", path);
if (unlink(path) < 0) {
if (errno == ENOENT)
continue;
return log_error_errno(errno, "Failed to remove '%s': %m", path);
}
flags |= reload;
log_info("Successfully removed masked network config '%s'.", path);
}
return reload_daemons(flags);
}
+3
View File
@@ -3,3 +3,6 @@
int verb_edit(int argc, char *argv[], void *userdata);
int verb_cat(int argc, char *argv[], void *userdata);
int verb_mask(int argc, char *argv[], void *userdata);
int verb_unmask(int argc, char *argv[], void *userdata);
+4
View File
@@ -2877,6 +2877,8 @@ static int help(void) {
" reload Reload .network and .netdev files\n"
" edit FILES|DEVICES... Edit network configuration files\n"
" cat FILES|DEVICES... Show network configuration files\n"
" mask FILES... Mask network configuration files\n"
" unmask FILES... Unmask network configuration files\n"
"\nOptions:\n"
" -h --help Show this help\n"
" --version Show package version\n"
@@ -3033,6 +3035,8 @@ static int networkctl_main(int argc, char *argv[]) {
{ "reload", 1, 1, VERB_ONLINE_ONLY, verb_reload },
{ "edit", 2, VERB_ANY, 0, verb_edit },
{ "cat", 2, VERB_ANY, 0, verb_cat },
{ "mask", 2, VERB_ANY, 0, verb_mask },
{ "unmask", 2, VERB_ANY, 0, verb_unmask },
{}
};