Files
systemd/src/network/networkctl.c
T
Yu Watanabe 05bdf4bfa9 compress: split compress_blob() and friends to minimize dlopen dependencies
Previously, even though sd-journal does not support bzip2 and gzip
compression, the dlopen ELF notes for those libraries were still being
attached to libsystemd.so and various journal-handling executables.
This occurred because the unified compression/decompression interfaces
handled all formats unconditionally, causing the compiler and linker to
pull in all associated dlopen notes across the board.

To resolve this, split these functions into generic and journal-specific
variants (e.g., introducing compress_blob_journal() and decompress_blob_journal()).
The journal-specific variants only handle formats actually supported by
the journal (LZ4, XZ, and ZSTD).

By updating sd-journal, journald, journalctl, and related utilities to
use these new `_journal` interfaces and switching them to the narrower
COMPRESS_JOURNAL_NOTE macro, we ensure that unnecessary dlopen notes
(for bzip2 and gzip) are no longer embedded into these binaries.
2026-07-10 16:35:19 +09:00

227 lines
8.4 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-json.h"
#include "alloc-util.h"
#include "build.h"
#include "dlopen-note.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "logs-show.h"
#include "main-func.h"
#include "networkctl.h"
#include "networkctl-address-label.h"
#include "networkctl-config-file.h"
#include "networkctl-dhcp-lease.h"
#include "networkctl-list.h"
#include "networkctl-lldp.h"
#include "networkctl-misc.h"
#include "networkctl-status-link.h"
#include "options.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
#include "verbs.h"
PagerFlags arg_pager_flags = 0;
bool arg_legend = true;
bool arg_no_reload = false;
bool arg_all = false;
bool arg_stats = false;
bool arg_full = false;
bool arg_runtime = false;
bool arg_stdin = false;
unsigned arg_lines = 10;
char *arg_drop_in = NULL;
sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
bool arg_ask_password = true;
STATIC_DESTRUCTOR_REGISTER(arg_drop_in, freep);
VERB_SCOPE(, verb_list_links, "list", "[PATTERN...]", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY,
"List links");
VERB_SCOPE(, verb_link_status, "status", "[PATTERN...]", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY,
"Show link status");
VERB_SCOPE(, verb_dhcp_lease, "dhcp-lease", "INTERFACE [CODE[:FORMAT]...]", 2, VERB_ANY, VERB_ONLINE_ONLY,
"Show DHCP lease");
VERB_SCOPE(, verb_link_lldp_status, "lldp", "[PATTERN...]", VERB_ANY, VERB_ANY, 0,
"Show LLDP neighbors");
VERB_SCOPE(, verb_list_address_labels, "label", NULL, 1, 1, 0,
"Show current address label entries in the kernel");
VERB_SCOPE(, verb_link_delete, "delete", "DEVICES...", 2, VERB_ANY, 0,
"Delete virtual netdevs");
VERB_SCOPE(, verb_link_varlink_simple_method, "up", "DEVICES...", 2, VERB_ANY, 0,
"Bring devices up");
VERB_SCOPE(, verb_link_varlink_simple_method, "down", "DEVICES...", 2, VERB_ANY, 0,
"Bring devices down");
VERB_SCOPE(, verb_link_varlink_simple_method, "renew", "DEVICES...", 2, VERB_ANY, VERB_ONLINE_ONLY,
"Renew dynamic configurations");
VERB_SCOPE(, verb_link_varlink_simple_method, "forcerenew", "DEVICES...", 2, VERB_ANY, VERB_ONLINE_ONLY,
"Trigger DHCP reconfiguration of all connected clients");
VERB_SCOPE(, verb_link_varlink_simple_method, "reconfigure", "DEVICES...", 2, VERB_ANY, VERB_ONLINE_ONLY,
"Reconfigure interfaces");
VERB_SCOPE(, verb_reload, "reload", NULL, 1, 1, VERB_ONLINE_ONLY,
"Reload .network and .netdev files");
VERB_SCOPE(, verb_edit, "edit", "FILES|DEVICES...", 2, VERB_ANY, 0,
"Edit network configuration files");
VERB_SCOPE(, verb_cat, "cat", "[FILES|DEVICES...]", 1, VERB_ANY, 0,
"Show network configuration files");
VERB_SCOPE(, verb_mask, "mask", "FILES...", 2, VERB_ANY, 0,
"Mask network configuration files");
VERB_SCOPE(, verb_unmask, "unmask", "FILES...", 2, VERB_ANY, 0,
"Unmask network configuration files");
VERB_SCOPE(, verb_persistent_storage, "persistent-storage", "BOOL", 2, 2, 0,
"Notify systemd-networkd if persistent storage is ready");
static int help(void) {
_cleanup_(table_unrefp) Table *verbs = NULL, *options = NULL;
int r;
r = verbs_get_help_table(&verbs);
if (r < 0)
return r;
r = option_parser_get_help_table(&options);
if (r < 0)
return r;
(void) table_sync_column_widths(0, verbs, options);
help_cmdline("[OPTIONS...] COMMAND");
help_abstract("Query and control the networking subsystem.");
help_section("Commands");
r = table_print_or_warn(verbs);
if (r < 0)
return r;
help_section("Options");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("networkctl", "1");
return 0;
}
VERB_COMMON_HELP_HIDDEN(help);
static int parse_argv(int argc, char *argv[], char ***remaining_args) {
int r;
assert(argc >= 0);
assert(argv);
assert(remaining_args);
OptionParser opts = { argc, argv };
FOREACH_OPTION_OR_RETURN(c, &opts)
switch (c) {
OPTION_COMMON_HELP:
return help();
OPTION_COMMON_VERSION:
return version();
OPTION_COMMON_NO_PAGER:
arg_pager_flags |= PAGER_DISABLE;
break;
OPTION_COMMON_NO_LEGEND:
arg_legend = false;
break;
OPTION_COMMON_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
OPTION('a', "all", NULL, "Show status for all links"):
arg_all = true;
break;
OPTION('s', "stats", NULL, "Show detailed link statistics"):
arg_stats = true;
break;
OPTION('l', "full", NULL, "Do not ellipsize output"):
arg_full = true;
break;
OPTION('n', "lines", "INTEGER", "Number of journal entries to show"):
r = safe_atou(opts.arg, &arg_lines);
if (r < 0)
return log_error_errno(r, "Failed to parse --lines value '%s': %m", opts.arg);
break;
OPTION_COMMON_JSON:
r = parse_json_argument(opts.arg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
OPTION_LONG("no-reload", NULL,
"Do not reload systemd-networkd or systemd-udevd after editing network config"):
arg_no_reload = true;
break;
OPTION_LONG("drop-in", "NAME",
"Edit specified drop-in instead of main config file"):
if (isempty(opts.arg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name.");
if (!endswith(opts.arg, ".conf")) {
char *conf;
conf = strjoin(opts.arg, ".conf");
if (!conf)
return log_oom();
free_and_replace(arg_drop_in, conf);
} else {
r = free_and_strdup(&arg_drop_in, opts.arg);
if (r < 0)
return log_oom();
}
if (!filename_is_valid(arg_drop_in))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid drop-in file name '%s'.", arg_drop_in);
break;
OPTION_LONG("runtime", NULL, "Edit runtime config files"):
arg_runtime = true;
break;
OPTION_LONG("stdin", NULL, "Read new contents of edited file from stdin"):
arg_stdin = true;
break;
}
*remaining_args = option_parser_get_args(&opts);
return 1;
}
static int run(int argc, char* argv[]) {
char **args = NULL;
int r;
COMPRESS_JOURNAL_NOTE;
LIBSELINUX_NOTE(recommended);
log_setup();
r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
journal_browse_prepare();
return dispatch_verb(args, NULL);
}
DEFINE_MAIN_FUNCTION(run);