mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 16:37:19 +09:00
263 lines
11 KiB
C
263 lines
11 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include <getopt.h>
|
|
|
|
#include "sd-json.h"
|
|
|
|
#include "alloc-util.h"
|
|
#include "build.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-list.h"
|
|
#include "networkctl-lldp.h"
|
|
#include "networkctl-misc.h"
|
|
#include "networkctl-status-link.h"
|
|
#include "parse-argument.h"
|
|
#include "parse-util.h"
|
|
#include "path-util.h"
|
|
#include "pretty-print.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);
|
|
|
|
static int help(void) {
|
|
_cleanup_free_ char *link = NULL;
|
|
int r;
|
|
|
|
r = terminal_urlify_man("networkctl", "1", &link);
|
|
if (r < 0)
|
|
return log_oom();
|
|
|
|
printf("%s [OPTIONS...] COMMAND\n\n"
|
|
"%sQuery and control the networking subsystem.%s\n"
|
|
"\nCommands:\n"
|
|
" list [PATTERN...] List links\n"
|
|
" status [PATTERN...] Show link status\n"
|
|
" lldp [PATTERN...] Show LLDP neighbors\n"
|
|
" label Show current address label entries in the kernel\n"
|
|
" delete DEVICES... Delete virtual netdevs\n"
|
|
" up DEVICES... Bring devices up\n"
|
|
" down DEVICES... Bring devices down\n"
|
|
" renew DEVICES... Renew dynamic configurations\n"
|
|
" forcerenew DEVICES... Trigger DHCP reconfiguration of all connected clients\n"
|
|
" reconfigure DEVICES... Reconfigure interfaces\n"
|
|
" 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"
|
|
" persistent-storage BOOL\n"
|
|
" Notify systemd-networkd if persistent storage is ready\n"
|
|
"\nOptions:\n"
|
|
" -h --help Show this help\n"
|
|
" --version Show package version\n"
|
|
" --no-pager Do not pipe output into a pager\n"
|
|
" --no-legend Do not show the headers and footers\n"
|
|
" --no-ask-password Do not prompt for password\n"
|
|
" -a --all Show status for all links\n"
|
|
" -s --stats Show detailed link statistics\n"
|
|
" -l --full Do not ellipsize output\n"
|
|
" -n --lines=INTEGER Number of journal entries to show\n"
|
|
" --json=pretty|short|off\n"
|
|
" Generate JSON output\n"
|
|
" --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"
|
|
" --stdin Read new contents of edited file from stdin\n"
|
|
"\nSee the %s for details.\n",
|
|
program_invocation_short_name,
|
|
ansi_highlight(),
|
|
ansi_normal(),
|
|
link);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int parse_argv(int argc, char *argv[]) {
|
|
enum {
|
|
ARG_VERSION = 0x100,
|
|
ARG_NO_PAGER,
|
|
ARG_NO_LEGEND,
|
|
ARG_NO_ASK_PASSWORD,
|
|
ARG_JSON,
|
|
ARG_NO_RELOAD,
|
|
ARG_DROP_IN,
|
|
ARG_RUNTIME,
|
|
ARG_STDIN,
|
|
};
|
|
|
|
static const struct option options[] = {
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "version", no_argument, NULL, ARG_VERSION },
|
|
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
|
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
|
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
|
{ "all", no_argument, NULL, 'a' },
|
|
{ "stats", no_argument, NULL, 's' },
|
|
{ "full", no_argument, NULL, 'l' },
|
|
{ "lines", required_argument, NULL, 'n' },
|
|
{ "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 },
|
|
{ "stdin", no_argument, NULL, ARG_STDIN },
|
|
{}
|
|
};
|
|
|
|
int c, r;
|
|
|
|
assert(argc >= 0);
|
|
assert(argv);
|
|
|
|
while ((c = getopt_long(argc, argv, "hasln:", options, NULL)) >= 0) {
|
|
|
|
switch (c) {
|
|
|
|
case 'h':
|
|
return help();
|
|
|
|
case ARG_VERSION:
|
|
return version();
|
|
|
|
case ARG_NO_PAGER:
|
|
arg_pager_flags |= PAGER_DISABLE;
|
|
break;
|
|
|
|
case ARG_NO_LEGEND:
|
|
arg_legend = false;
|
|
break;
|
|
|
|
case ARG_NO_RELOAD:
|
|
arg_no_reload = true;
|
|
break;
|
|
|
|
case ARG_NO_ASK_PASSWORD:
|
|
arg_ask_password = false;
|
|
break;
|
|
|
|
case ARG_RUNTIME:
|
|
arg_runtime = true;
|
|
break;
|
|
|
|
case ARG_STDIN:
|
|
arg_stdin = true;
|
|
break;
|
|
|
|
case ARG_DROP_IN:
|
|
if (isempty(optarg))
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name.");
|
|
|
|
if (!endswith(optarg, ".conf")) {
|
|
char *conf;
|
|
|
|
conf = strjoin(optarg, ".conf");
|
|
if (!conf)
|
|
return log_oom();
|
|
|
|
free_and_replace(arg_drop_in, conf);
|
|
} else {
|
|
r = free_and_strdup(&arg_drop_in, optarg);
|
|
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;
|
|
|
|
case 'a':
|
|
arg_all = true;
|
|
break;
|
|
|
|
case 's':
|
|
arg_stats = true;
|
|
break;
|
|
|
|
case 'l':
|
|
arg_full = true;
|
|
break;
|
|
|
|
case 'n':
|
|
if (safe_atou(optarg, &arg_lines) < 0)
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
"Failed to parse lines '%s'", optarg);
|
|
break;
|
|
|
|
case ARG_JSON:
|
|
r = parse_json_argument(optarg, &arg_json_format_flags);
|
|
if (r <= 0)
|
|
return r;
|
|
break;
|
|
|
|
case '?':
|
|
return -EINVAL;
|
|
|
|
default:
|
|
assert_not_reached();
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int networkctl_main(int argc, char *argv[]) {
|
|
static const Verb verbs[] = {
|
|
{ "list", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_links },
|
|
{ "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, link_status },
|
|
{ "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
|
|
{ "label", 1, 1, 0, list_address_labels },
|
|
{ "delete", 2, VERB_ANY, 0, link_delete },
|
|
{ "up", 2, VERB_ANY, 0, link_up_down },
|
|
{ "down", 2, VERB_ANY, 0, link_up_down },
|
|
{ "renew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_renew },
|
|
{ "forcerenew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_force_renew },
|
|
{ "reconfigure", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_reconfigure },
|
|
{ "reload", 1, 1, VERB_ONLINE_ONLY, verb_reload },
|
|
{ "edit", 2, VERB_ANY, 0, verb_edit },
|
|
{ "cat", 1, VERB_ANY, 0, verb_cat },
|
|
{ "mask", 2, VERB_ANY, 0, verb_mask },
|
|
{ "unmask", 2, VERB_ANY, 0, verb_unmask },
|
|
{ "persistent-storage", 2, 2, 0, verb_persistent_storage },
|
|
{}
|
|
};
|
|
|
|
return dispatch_verb(argc, argv, verbs, NULL);
|
|
}
|
|
|
|
static int run(int argc, char* argv[]) {
|
|
int r;
|
|
|
|
log_setup();
|
|
|
|
r = parse_argv(argc, argv);
|
|
if (r <= 0)
|
|
return r;
|
|
|
|
journal_browse_prepare();
|
|
|
|
return networkctl_main(argc, argv);
|
|
}
|
|
|
|
DEFINE_MAIN_FUNCTION(run);
|