]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/generator/main.c
Merge pull request #31648 from neighbourhoodie/review-content
[thirdparty/systemd.git] / src / network / generator / main.c
CommitLineData
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
19static const char *arg_root = NULL;
20
21static 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
55static 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
86static 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
120static 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
144static 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
154static 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
194static 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
247DEFINE_MAIN_FUNCTION(run);