]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
ee8c4568 | 2 | |
ee8c4568 LP |
3 | #include <getopt.h> |
4 | ||
1e35e81b DDM |
5 | #include "sd-json.h" |
6 | ||
decad482 | 7 | #include "alloc-util.h" |
d6b4d1c7 | 8 | #include "build.h" |
93a1f792 | 9 | #include "log.h" |
fad3feec | 10 | #include "logs-show.h" |
4e2ca442 | 11 | #include "main-func.h" |
15fde154 | 12 | #include "networkctl.h" |
1bf49198 | 13 | #include "networkctl-address-label.h" |
15fde154 | 14 | #include "networkctl-config-file.h" |
1bf49198 YW |
15 | #include "networkctl-list.h" |
16 | #include "networkctl-lldp.h" | |
17 | #include "networkctl-misc.h" | |
18 | #include "networkctl-status-link.h" | |
bfc2b05e | 19 | #include "parse-argument.h" |
6bedfcbb | 20 | #include "parse-util.h" |
96bab8fd | 21 | #include "path-util.h" |
294bf0c3 | 22 | #include "pretty-print.h" |
baa3fadf | 23 | #include "string-util.h" |
3f6fd1ba | 24 | #include "verbs.h" |
8d07de25 | 25 | |
15fde154 MY |
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; | |
119cba78 | 33 | bool arg_stdin = false; |
15fde154 MY |
34 | unsigned arg_lines = 10; |
35 | char *arg_drop_in = NULL; | |
309a747f | 36 | sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF; |
67899e3e | 37 | bool arg_ask_password = true; |
bfc2b05e | 38 | |
96bab8fd MY |
39 | STATIC_DESTRUCTOR_REGISTER(arg_drop_in, freep); |
40 | ||
37ec0fdd LP |
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 | ||
353b2baa LP |
49 | printf("%s [OPTIONS...] COMMAND\n\n" |
50 | "%sQuery and control the networking subsystem.%s\n" | |
a459b24f | 51 | "\nCommands:\n" |
8dc85c5e YW |
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" | |
c30ffcee SS |
57 | " up DEVICES... Bring devices up\n" |
58 | " down DEVICES... Bring devices down\n" | |
8dc85c5e | 59 | " renew DEVICES... Renew dynamic configurations\n" |
3efdd6af | 60 | " forcerenew DEVICES... Trigger DHCP reconfiguration of all connected clients\n" |
8dc85c5e YW |
61 | " reconfigure DEVICES... Reconfigure interfaces\n" |
62 | " reload Reload .network and .netdev files\n" | |
96bab8fd | 63 | " edit FILES|DEVICES... Edit network configuration files\n" |
78281bd5 | 64 | " cat [FILES|DEVICES...] Show network configuration files\n" |
28bb29cb MY |
65 | " mask FILES... Mask network configuration files\n" |
66 | " unmask FILES... Unmask network configuration files\n" | |
91676b64 YW |
67 | " persistent-storage BOOL\n" |
68 | " Notify systemd-networkd if persistent storage is ready\n" | |
353b2baa | 69 | "\nOptions:\n" |
8dc85c5e YW |
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" | |
21f31f23 | 74 | " --no-ask-password Do not prompt for password\n" |
8dc85c5e | 75 | " -a --all Show status for all links\n" |
ba669952 | 76 | " -s --stats Show detailed link statistics\n" |
10c71c36 YW |
77 | " -l --full Do not ellipsize output\n" |
78 | " -n --lines=INTEGER Number of journal entries to show\n" | |
bfc2b05e YW |
79 | " --json=pretty|short|off\n" |
80 | " Generate JSON output\n" | |
96bab8fd MY |
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" | |
2b98926f | 84 | " --runtime Edit runtime config files\n" |
119cba78 | 85 | " --stdin Read new contents of edited file from stdin\n" |
bc556335 DDM |
86 | "\nSee the %s for details.\n", |
87 | program_invocation_short_name, | |
88 | ansi_highlight(), | |
89 | ansi_normal(), | |
90 | link); | |
37ec0fdd LP |
91 | |
92 | return 0; | |
ee8c4568 LP |
93 | } |
94 | ||
95 | static int parse_argv(int argc, char *argv[]) { | |
ee8c4568 LP |
96 | enum { |
97 | ARG_VERSION = 0x100, | |
98 | ARG_NO_PAGER, | |
99 | ARG_NO_LEGEND, | |
21f31f23 | 100 | ARG_NO_ASK_PASSWORD, |
bfc2b05e | 101 | ARG_JSON, |
96bab8fd MY |
102 | ARG_NO_RELOAD, |
103 | ARG_DROP_IN, | |
2b98926f | 104 | ARG_RUNTIME, |
119cba78 | 105 | ARG_STDIN, |
ee8c4568 LP |
106 | }; |
107 | ||
108 | static const struct option options[] = { | |
21f31f23 YW |
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 }, | |
ee8c4568 LP |
123 | {} |
124 | }; | |
125 | ||
bfc2b05e | 126 | int c, r; |
ee8c4568 LP |
127 | |
128 | assert(argc >= 0); | |
129 | assert(argv); | |
130 | ||
10c71c36 | 131 | while ((c = getopt_long(argc, argv, "hasln:", options, NULL)) >= 0) { |
ee8c4568 LP |
132 | |
133 | switch (c) { | |
134 | ||
135 | case 'h': | |
37ec0fdd | 136 | return help(); |
ee8c4568 LP |
137 | |
138 | case ARG_VERSION: | |
3f6fd1ba | 139 | return version(); |
ee8c4568 LP |
140 | |
141 | case ARG_NO_PAGER: | |
0221d68a | 142 | arg_pager_flags |= PAGER_DISABLE; |
ee8c4568 LP |
143 | break; |
144 | ||
145 | case ARG_NO_LEGEND: | |
146 | arg_legend = false; | |
147 | break; | |
148 | ||
96bab8fd MY |
149 | case ARG_NO_RELOAD: |
150 | arg_no_reload = true; | |
151 | break; | |
152 | ||
21f31f23 YW |
153 | case ARG_NO_ASK_PASSWORD: |
154 | arg_ask_password = false; | |
155 | break; | |
156 | ||
2b98926f MY |
157 | case ARG_RUNTIME: |
158 | arg_runtime = true; | |
159 | break; | |
160 | ||
119cba78 MY |
161 | case ARG_STDIN: |
162 | arg_stdin = true; | |
163 | break; | |
164 | ||
96bab8fd MY |
165 | case ARG_DROP_IN: |
166 | if (isempty(optarg)) | |
167 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name."); | |
168 | ||
5de8264b FS |
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 | } | |
96bab8fd MY |
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 | ||
9085f64a LP |
189 | case 'a': |
190 | arg_all = true; | |
191 | break; | |
192 | ||
a459b24f YW |
193 | case 's': |
194 | arg_stats = true; | |
195 | break; | |
196 | ||
10c71c36 YW |
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 | ||
bfc2b05e YW |
207 | case ARG_JSON: |
208 | r = parse_json_argument(optarg, &arg_json_format_flags); | |
209 | if (r <= 0) | |
210 | return r; | |
211 | break; | |
212 | ||
ee8c4568 LP |
213 | case '?': |
214 | return -EINVAL; | |
215 | ||
216 | default: | |
04499a70 | 217 | assert_not_reached(); |
ee8c4568 LP |
218 | } |
219 | } | |
220 | ||
221 | return 1; | |
222 | } | |
223 | ||
445f0d8b | 224 | static int networkctl_main(int argc, char *argv[]) { |
15c3626e | 225 | static const Verb verbs[] = { |
91676b64 YW |
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 }, | |
78281bd5 | 238 | { "cat", 1, VERB_ANY, 0, verb_cat }, |
91676b64 YW |
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 }, | |
266b5389 | 242 | {} |
ee8c4568 LP |
243 | }; |
244 | ||
445f0d8b | 245 | return dispatch_verb(argc, argv, verbs, NULL); |
58fb3678 LP |
246 | } |
247 | ||
4e2ca442 | 248 | static int run(int argc, char* argv[]) { |
ee8c4568 LP |
249 | int r; |
250 | ||
d2acb93d | 251 | log_setup(); |
ee8c4568 LP |
252 | |
253 | r = parse_argv(argc, argv); | |
254 | if (r <= 0) | |
4e2ca442 | 255 | return r; |
ee8c4568 | 256 | |
fad3feec MY |
257 | journal_browse_prepare(); |
258 | ||
445f0d8b | 259 | return networkctl_main(argc, argv); |
ee8c4568 | 260 | } |
4e2ca442 ZJS |
261 | |
262 | DEFINE_MAIN_FUNCTION(run); |