]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkctl.c
f9aa40ba1bd62aac8c198fd308c281ba26445b1b
[thirdparty/systemd.git] / src / network / networkctl.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4
5 #include "sd-json.h"
6
7 #include "alloc-util.h"
8 #include "build.h"
9 #include "log.h"
10 #include "logs-show.h"
11 #include "main-func.h"
12 #include "networkctl.h"
13 #include "networkctl-address-label.h"
14 #include "networkctl-config-file.h"
15 #include "networkctl-list.h"
16 #include "networkctl-lldp.h"
17 #include "networkctl-misc.h"
18 #include "networkctl-status-link.h"
19 #include "parse-argument.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "pretty-print.h"
23 #include "string-util.h"
24 #include "verbs.h"
25
26 PagerFlags arg_pager_flags = 0;
27 bool arg_legend = true;
28 bool arg_no_reload = false;
29 bool arg_all = false;
30 bool arg_stats = false;
31 bool arg_full = false;
32 bool arg_runtime = false;
33 bool arg_stdin = false;
34 unsigned arg_lines = 10;
35 char *arg_drop_in = NULL;
36 sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
37 bool arg_ask_password = true;
38
39 STATIC_DESTRUCTOR_REGISTER(arg_drop_in, freep);
40
41 static int help(void) {
42 _cleanup_free_ char *link = NULL;
43 int r;
44
45 r = terminal_urlify_man("networkctl", "1", &link);
46 if (r < 0)
47 return log_oom();
48
49 printf("%s [OPTIONS...] COMMAND\n\n"
50 "%sQuery and control the networking subsystem.%s\n"
51 "\nCommands:\n"
52 " list [PATTERN...] List links\n"
53 " status [PATTERN...] Show link status\n"
54 " lldp [PATTERN...] Show LLDP neighbors\n"
55 " label Show current address label entries in the kernel\n"
56 " delete DEVICES... Delete virtual netdevs\n"
57 " up DEVICES... Bring devices up\n"
58 " down DEVICES... Bring devices down\n"
59 " renew DEVICES... Renew dynamic configurations\n"
60 " forcerenew DEVICES... Trigger DHCP reconfiguration of all connected clients\n"
61 " reconfigure DEVICES... Reconfigure interfaces\n"
62 " reload Reload .network and .netdev files\n"
63 " edit FILES|DEVICES... Edit network configuration files\n"
64 " cat [FILES|DEVICES...] Show network configuration files\n"
65 " mask FILES... Mask network configuration files\n"
66 " unmask FILES... Unmask network configuration files\n"
67 " persistent-storage BOOL\n"
68 " Notify systemd-networkd if persistent storage is ready\n"
69 "\nOptions:\n"
70 " -h --help Show this help\n"
71 " --version Show package version\n"
72 " --no-pager Do not pipe output into a pager\n"
73 " --no-legend Do not show the headers and footers\n"
74 " --no-ask-password Do not prompt for password\n"
75 " -a --all Show status for all links\n"
76 " -s --stats Show detailed link statistics\n"
77 " -l --full Do not ellipsize output\n"
78 " -n --lines=INTEGER Number of journal entries to show\n"
79 " --json=pretty|short|off\n"
80 " Generate JSON output\n"
81 " --no-reload Do not reload systemd-networkd or systemd-udevd\n"
82 " after editing network config\n"
83 " --drop-in=NAME Edit specified drop-in instead of main config file\n"
84 " --runtime Edit runtime config files\n"
85 " --stdin Read new contents of edited file from stdin\n"
86 "\nSee the %s for details.\n",
87 program_invocation_short_name,
88 ansi_highlight(),
89 ansi_normal(),
90 link);
91
92 return 0;
93 }
94
95 static int parse_argv(int argc, char *argv[]) {
96 enum {
97 ARG_VERSION = 0x100,
98 ARG_NO_PAGER,
99 ARG_NO_LEGEND,
100 ARG_NO_ASK_PASSWORD,
101 ARG_JSON,
102 ARG_NO_RELOAD,
103 ARG_DROP_IN,
104 ARG_RUNTIME,
105 ARG_STDIN,
106 };
107
108 static const struct option options[] = {
109 { "help", no_argument, NULL, 'h' },
110 { "version", no_argument, NULL, ARG_VERSION },
111 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
112 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
113 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
114 { "all", no_argument, NULL, 'a' },
115 { "stats", no_argument, NULL, 's' },
116 { "full", no_argument, NULL, 'l' },
117 { "lines", required_argument, NULL, 'n' },
118 { "json", required_argument, NULL, ARG_JSON },
119 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
120 { "drop-in", required_argument, NULL, ARG_DROP_IN },
121 { "runtime", no_argument, NULL, ARG_RUNTIME },
122 { "stdin", no_argument, NULL, ARG_STDIN },
123 {}
124 };
125
126 int c, r;
127
128 assert(argc >= 0);
129 assert(argv);
130
131 while ((c = getopt_long(argc, argv, "hasln:", options, NULL)) >= 0) {
132
133 switch (c) {
134
135 case 'h':
136 return help();
137
138 case ARG_VERSION:
139 return version();
140
141 case ARG_NO_PAGER:
142 arg_pager_flags |= PAGER_DISABLE;
143 break;
144
145 case ARG_NO_LEGEND:
146 arg_legend = false;
147 break;
148
149 case ARG_NO_RELOAD:
150 arg_no_reload = true;
151 break;
152
153 case ARG_NO_ASK_PASSWORD:
154 arg_ask_password = false;
155 break;
156
157 case ARG_RUNTIME:
158 arg_runtime = true;
159 break;
160
161 case ARG_STDIN:
162 arg_stdin = true;
163 break;
164
165 case ARG_DROP_IN:
166 if (isempty(optarg))
167 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name.");
168
169 if (!endswith(optarg, ".conf")) {
170 char *conf;
171
172 conf = strjoin(optarg, ".conf");
173 if (!conf)
174 return log_oom();
175
176 free_and_replace(arg_drop_in, conf);
177 } else {
178 r = free_and_strdup(&arg_drop_in, optarg);
179 if (r < 0)
180 return log_oom();
181 }
182
183 if (!filename_is_valid(arg_drop_in))
184 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
185 "Invalid drop-in file name '%s'.", arg_drop_in);
186
187 break;
188
189 case 'a':
190 arg_all = true;
191 break;
192
193 case 's':
194 arg_stats = true;
195 break;
196
197 case 'l':
198 arg_full = true;
199 break;
200
201 case 'n':
202 if (safe_atou(optarg, &arg_lines) < 0)
203 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
204 "Failed to parse lines '%s'", optarg);
205 break;
206
207 case ARG_JSON:
208 r = parse_json_argument(optarg, &arg_json_format_flags);
209 if (r <= 0)
210 return r;
211 break;
212
213 case '?':
214 return -EINVAL;
215
216 default:
217 assert_not_reached();
218 }
219 }
220
221 return 1;
222 }
223
224 static int networkctl_main(int argc, char *argv[]) {
225 static const Verb verbs[] = {
226 { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_links },
227 { "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, link_status },
228 { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
229 { "label", 1, 1, 0, list_address_labels },
230 { "delete", 2, VERB_ANY, 0, link_delete },
231 { "up", 2, VERB_ANY, 0, link_up_down },
232 { "down", 2, VERB_ANY, 0, link_up_down },
233 { "renew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_renew },
234 { "forcerenew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_force_renew },
235 { "reconfigure", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_reconfigure },
236 { "reload", 1, 1, VERB_ONLINE_ONLY, verb_reload },
237 { "edit", 2, VERB_ANY, 0, verb_edit },
238 { "cat", 1, VERB_ANY, 0, verb_cat },
239 { "mask", 2, VERB_ANY, 0, verb_mask },
240 { "unmask", 2, VERB_ANY, 0, verb_unmask },
241 { "persistent-storage", 2, 2, 0, verb_persistent_storage },
242 {}
243 };
244
245 return dispatch_verb(argc, argv, verbs, NULL);
246 }
247
248 static int run(int argc, char* argv[]) {
249 int r;
250
251 log_setup();
252
253 r = parse_argv(argc, argv);
254 if (r <= 0)
255 return r;
256
257 journal_browse_prepare();
258
259 return networkctl_main(argc, argv);
260 }
261
262 DEFINE_MAIN_FUNCTION(run);