]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
426c1d38 YW |
2 | |
3 | #include <getopt.h> | |
4 | ||
d6b4d1c7 | 5 | #include "build.h" |
1a302855 | 6 | #include "creds-util.h" |
426c1d38 | 7 | #include "fd-util.h" |
f3e4d042 | 8 | #include "fs-util.h" |
426c1d38 YW |
9 | #include "generator.h" |
10 | #include "macro.h" | |
11 | #include "main-func.h" | |
12 | #include "mkdir.h" | |
13 | #include "network-generator.h" | |
14 | #include "path-util.h" | |
15 | #include "proc-cmdline.h" | |
16 | ||
a40e4958 | 17 | #define NETWORK_UNIT_DIRECTORY "/run/systemd/network/" |
426c1d38 YW |
18 | |
19 | static const char *arg_root = NULL; | |
20 | ||
21 | static int network_save(Network *network, const char *dest_dir) { | |
f3e4d042 | 22 | _cleanup_(unlink_and_freep) char *temp_path = NULL; |
426c1d38 | 23 | _cleanup_fclose_ FILE *f = NULL; |
657152a4 | 24 | _cleanup_free_ char *p = NULL; |
426c1d38 YW |
25 | int r; |
26 | ||
27 | assert(network); | |
28 | ||
7ceb76b6 LP |
29 | r = generator_open_unit_file_full( |
30 | dest_dir, | |
31 | /* source= */ NULL, | |
32 | /* name= */ NULL, | |
33 | &f, | |
34 | /* ret_final_path= */ NULL, | |
35 | &temp_path); | |
f3e4d042 AAF |
36 | if (r < 0) |
37 | return r; | |
38 | ||
39 | network_dump(network, f); | |
40 | ||
657152a4 YW |
41 | if (asprintf(&p, "%s/%s-%s.network", |
42 | dest_dir, | |
b94f59b9 | 43 | isempty(network->ifname) ? "71" : "70", |
657152a4 | 44 | isempty(network->ifname) ? "default" : network->ifname) < 0) |
f3e4d042 AAF |
45 | return log_oom(); |
46 | ||
47 | r = conservative_rename(temp_path, p); | |
426c1d38 | 48 | if (r < 0) |
3cb61808 | 49 | return log_error_errno(r, "Failed to rename '%s' to '%s': %m", temp_path, p); |
426c1d38 | 50 | |
f3e4d042 | 51 | temp_path = mfree(temp_path); |
426c1d38 YW |
52 | return 0; |
53 | } | |
54 | ||
55 | static int netdev_save(NetDev *netdev, const char *dest_dir) { | |
f3e4d042 | 56 | _cleanup_(unlink_and_freep) char *temp_path = NULL; |
426c1d38 | 57 | _cleanup_fclose_ FILE *f = NULL; |
657152a4 | 58 | _cleanup_free_ char *p = NULL; |
426c1d38 YW |
59 | int r; |
60 | ||
61 | assert(netdev); | |
62 | ||
7ceb76b6 LP |
63 | r = generator_open_unit_file_full( |
64 | dest_dir, | |
65 | /* source= */ NULL, | |
66 | /* name= */ NULL, | |
67 | &f, | |
68 | /* ret_final_path= */ NULL, | |
69 | &temp_path); | |
f3e4d042 AAF |
70 | if (r < 0) |
71 | return r; | |
72 | ||
73 | netdev_dump(netdev, f); | |
74 | ||
b94f59b9 | 75 | if (asprintf(&p, "%s/70-%s.netdev", dest_dir, netdev->ifname) < 0) |
f3e4d042 AAF |
76 | return log_oom(); |
77 | ||
78 | r = conservative_rename(temp_path, p); | |
426c1d38 | 79 | if (r < 0) |
3cb61808 | 80 | return log_error_errno(r, "Failed to rename '%s' to '%s': %m", temp_path, p); |
426c1d38 | 81 | |
f3e4d042 | 82 | temp_path = mfree(temp_path); |
426c1d38 YW |
83 | return 0; |
84 | } | |
85 | ||
86 | static int link_save(Link *link, const char *dest_dir) { | |
f3e4d042 | 87 | _cleanup_(unlink_and_freep) char *temp_path = NULL; |
426c1d38 | 88 | _cleanup_fclose_ FILE *f = NULL; |
657152a4 | 89 | _cleanup_free_ char *p = NULL; |
426c1d38 YW |
90 | int r; |
91 | ||
92 | assert(link); | |
93 | ||
7ceb76b6 LP |
94 | r = generator_open_unit_file_full( |
95 | dest_dir, | |
96 | /* source= */ NULL, | |
97 | /* name= */ NULL, | |
98 | &f, | |
99 | /* ret_final_path= */ NULL, | |
100 | &temp_path); | |
f3e4d042 AAF |
101 | if (r < 0) |
102 | return r; | |
103 | ||
104 | link_dump(link, f); | |
105 | ||
657152a4 YW |
106 | if (asprintf(&p, "%s/%s-%s.link", |
107 | dest_dir, | |
b94f59b9 | 108 | !isempty(link->ifname) ? "70" : !hw_addr_is_null(&link->mac) ? "71" : "72", |
657152a4 | 109 | link->filename) < 0) |
f3e4d042 AAF |
110 | return log_oom(); |
111 | ||
112 | r = conservative_rename(temp_path, p); | |
426c1d38 | 113 | if (r < 0) |
3cb61808 | 114 | return log_error_errno(r, "Failed to rename '%s' to '%s': %m", temp_path, p); |
426c1d38 | 115 | |
f3e4d042 | 116 | temp_path = mfree(temp_path); |
426c1d38 YW |
117 | return 0; |
118 | } | |
119 | ||
120 | static int context_save(Context *context) { | |
121 | Network *network; | |
122 | NetDev *netdev; | |
123 | Link *link; | |
1339b950 | 124 | int r; |
426c1d38 | 125 | |
a40e4958 | 126 | const char *p = prefix_roota(arg_root, NETWORK_UNIT_DIRECTORY); |
426c1d38 YW |
127 | |
128 | r = mkdir_p(p, 0755); | |
129 | if (r < 0) | |
a40e4958 | 130 | return log_error_errno(r, "Failed to create directory " NETWORK_UNIT_DIRECTORY ": %m"); |
426c1d38 | 131 | |
1339b950 ZJS |
132 | HASHMAP_FOREACH(network, context->networks_by_name) |
133 | RET_GATHER(r, network_save(network, p)); | |
134 | ||
135 | HASHMAP_FOREACH(netdev, context->netdevs_by_name) | |
136 | RET_GATHER(r, netdev_save(netdev, p)); | |
137 | ||
138 | HASHMAP_FOREACH(link, context->links_by_filename) | |
139 | RET_GATHER(r, link_save(link, p)); | |
426c1d38 YW |
140 | |
141 | return r; | |
142 | } | |
143 | ||
144 | static int help(void) { | |
145 | printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n" | |
146 | " -h --help Show this help\n" | |
147 | " --version Show package version\n" | |
bc556335 DDM |
148 | " --root=PATH Operate on an alternate filesystem root\n", |
149 | program_invocation_short_name); | |
426c1d38 YW |
150 | |
151 | return 0; | |
152 | } | |
153 | ||
154 | static int parse_argv(int argc, char *argv[]) { | |
155 | enum { | |
156 | ARG_VERSION = 0x100, | |
157 | ARG_ROOT, | |
158 | }; | |
159 | static const struct option options[] = { | |
160 | { "help", no_argument, NULL, 'h' }, | |
161 | { "version", no_argument, NULL, ARG_VERSION }, | |
162 | { "root", required_argument, NULL, ARG_ROOT }, | |
163 | {}, | |
164 | }; | |
165 | int c; | |
166 | ||
167 | assert(argc >= 0); | |
168 | assert(argv); | |
169 | ||
170 | while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) | |
171 | ||
172 | switch (c) { | |
173 | ||
174 | case 'h': | |
175 | return help(); | |
176 | ||
177 | case ARG_VERSION: | |
178 | return version(); | |
179 | ||
180 | case ARG_ROOT: | |
181 | arg_root = optarg; | |
182 | break; | |
183 | ||
184 | case '?': | |
185 | return -EINVAL; | |
186 | ||
187 | default: | |
04499a70 | 188 | assert_not_reached(); |
426c1d38 YW |
189 | } |
190 | ||
191 | return 1; | |
192 | } | |
193 | ||
194 | static int run(int argc, char *argv[]) { | |
195 | _cleanup_(context_clear) Context context = {}; | |
1a302855 | 196 | int r, ret = 0; |
426c1d38 | 197 | |
8b24bcdf DDM |
198 | log_setup(); |
199 | ||
c9d85c22 DDM |
200 | umask(0022); |
201 | ||
426c1d38 YW |
202 | r = parse_argv(argc, argv); |
203 | if (r <= 0) | |
204 | return r; | |
205 | ||
206 | if (optind >= argc) { | |
207 | r = proc_cmdline_parse(parse_cmdline_item, &context, 0); | |
208 | if (r < 0) | |
209 | return log_warning_errno(r, "Failed to parse kernel command line: %m"); | |
210 | } else { | |
6fa8acfb | 211 | for (int i = optind; i < argc; i++) { |
426c1d38 YW |
212 | _cleanup_free_ char *word = NULL; |
213 | char *value; | |
214 | ||
215 | word = strdup(argv[i]); | |
216 | if (!word) | |
217 | return log_oom(); | |
218 | ||
219 | value = strchr(word, '='); | |
220 | if (value) | |
221 | *(value++) = 0; | |
222 | ||
223 | r = parse_cmdline_item(word, value, &context); | |
224 | if (r < 0) | |
225 | return log_warning_errno(r, "Failed to parse command line \"%s%s%s\": %m", | |
226 | word, value ? "=" : "", strempty(value)); | |
227 | } | |
228 | } | |
229 | ||
230 | r = context_merge_networks(&context); | |
231 | if (r < 0) | |
232 | return log_warning_errno(r, "Failed to merge multiple command line options: %m"); | |
233 | ||
1a302855 | 234 | RET_GATHER(ret, context_save(&context)); |
6c15a284 YW |
235 | |
236 | static const PickUpCredential table[] = { | |
e12e16e9 YW |
237 | { "network.conf.", "/run/systemd/networkd.conf.d/", ".conf" }, |
238 | { "network.link.", NETWORK_UNIT_DIRECTORY, ".link" }, | |
239 | { "network.netdev.", NETWORK_UNIT_DIRECTORY, ".netdev" }, | |
240 | { "network.network.", NETWORK_UNIT_DIRECTORY, ".network" }, | |
6c15a284 YW |
241 | }; |
242 | RET_GATHER(ret, pick_up_credentials(table, ELEMENTSOF(table))); | |
1a302855 LP |
243 | |
244 | return ret; | |
426c1d38 YW |
245 | } |
246 | ||
247 | DEFINE_MAIN_FUNCTION(run); |