]>
Commit | Line | Data |
---|---|---|
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); |