This shows the DHCP message of an acquired DHCP lease.
Example:
```
$ networkctl dhcp-lease eth0
Header:
KEY VALUE
Hardware Type: ETHER
Hardware Address: 41:42:43:31:32:33
Client Address: 192.0.2.123
Server Address: 192.0.2.1
Options:
CODE NAME DATA
1 subnet mask 255.255.255.0
3 router 192.0.2.1
6 domain name server 192.0.2.1
12 hostname test-node
15 domain name lan
28 broadcast address 192.0.2.255
42 NTP server 192.0.2.11
192.0.2.12
51 lease time 1d
53 message type 5
54 server identifier 192.0.2.1
58 renewal time 11h 5min 38s
59 rebinding time 20h 5min 38s
119 domain search hoge.example.com
foo.example.com
```
223 lines
8.3 KiB
C
223 lines
8.3 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "sd-json.h"
|
|
|
|
#include "alloc-util.h"
|
|
#include "build.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;
|
|
|
|
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);
|