]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/nspawn/nspawn-settings.c
Merge pull request #2525 from chaloulo/journal-remote-microhttp-max-memory-usage
[thirdparty/systemd.git] / src / nspawn / nspawn-settings.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "alloc-util.h"
23 #include "cap-list.h"
24 #include "conf-parser.h"
25 #include "nspawn-network.h"
26 #include "nspawn-settings.h"
27 #include "parse-util.h"
28 #include "process-util.h"
29 #include "strv.h"
30 #include "util.h"
31
32 int settings_load(FILE *f, const char *path, Settings **ret) {
33 _cleanup_(settings_freep) Settings *s = NULL;
34 int r;
35
36 assert(path);
37 assert(ret);
38
39 s = new0(Settings, 1);
40 if (!s)
41 return -ENOMEM;
42
43 s->start_mode = _START_MODE_INVALID;
44 s->personality = PERSONALITY_INVALID;
45
46 s->read_only = -1;
47 s->volatile_mode = _VOLATILE_MODE_INVALID;
48
49 s->private_network = -1;
50 s->network_veth = -1;
51
52 r = config_parse(NULL, path, f,
53 "Exec\0"
54 "Network\0"
55 "Files\0",
56 config_item_perf_lookup, nspawn_gperf_lookup,
57 false,
58 false,
59 true,
60 s);
61 if (r < 0)
62 return r;
63
64 *ret = s;
65 s = NULL;
66
67 return 0;
68 }
69
70 Settings* settings_free(Settings *s) {
71
72 if (!s)
73 return NULL;
74
75 strv_free(s->parameters);
76 strv_free(s->environment);
77 free(s->user);
78 free(s->working_directory);
79
80 strv_free(s->network_interfaces);
81 strv_free(s->network_macvlan);
82 strv_free(s->network_ipvlan);
83 strv_free(s->network_veth_extra);
84 free(s->network_bridge);
85 expose_port_free_all(s->expose_ports);
86
87 custom_mount_free_all(s->custom_mounts, s->n_custom_mounts);
88 free(s);
89
90 return NULL;
91 }
92
93 bool settings_private_network(Settings *s) {
94 assert(s);
95
96 return
97 s->private_network > 0 ||
98 s->network_veth > 0 ||
99 s->network_bridge ||
100 s->network_interfaces ||
101 s->network_macvlan ||
102 s->network_ipvlan ||
103 s->network_veth_extra;
104 }
105
106 bool settings_network_veth(Settings *s) {
107 assert(s);
108
109 return
110 s->network_veth > 0 ||
111 s->network_bridge;
112 }
113
114 DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode");
115
116 int config_parse_expose_port(
117 const char *unit,
118 const char *filename,
119 unsigned line,
120 const char *section,
121 unsigned section_line,
122 const char *lvalue,
123 int ltype,
124 const char *rvalue,
125 void *data,
126 void *userdata) {
127
128 Settings *s = data;
129 int r;
130
131 assert(filename);
132 assert(lvalue);
133 assert(rvalue);
134
135 r = expose_port_parse(&s->expose_ports, rvalue);
136 if (r == -EEXIST) {
137 log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue);
138 return 0;
139 }
140 if (r < 0) {
141 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse host port %s: %m", rvalue);
142 return 0;
143 }
144
145 return 0;
146 }
147
148 int config_parse_capability(
149 const char *unit,
150 const char *filename,
151 unsigned line,
152 const char *section,
153 unsigned section_line,
154 const char *lvalue,
155 int ltype,
156 const char *rvalue,
157 void *data,
158 void *userdata) {
159
160 uint64_t u = 0, *result = data;
161 int r;
162
163 assert(filename);
164 assert(lvalue);
165 assert(rvalue);
166
167 for (;;) {
168 _cleanup_free_ char *word = NULL;
169 int cap;
170
171 r = extract_first_word(&rvalue, &word, NULL, 0);
172 if (r < 0) {
173 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue);
174 return 0;
175 }
176 if (r == 0)
177 break;
178
179 cap = capability_from_name(word);
180 if (cap < 0) {
181 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability, ignoring: %s", word);
182 continue;
183 }
184
185 u |= 1 << ((uint64_t) cap);
186 }
187
188 if (u == 0)
189 return 0;
190
191 *result |= u;
192 return 0;
193 }
194
195 int config_parse_id128(
196 const char *unit,
197 const char *filename,
198 unsigned line,
199 const char *section,
200 unsigned section_line,
201 const char *lvalue,
202 int ltype,
203 const char *rvalue,
204 void *data,
205 void *userdata) {
206
207 sd_id128_t t, *result = data;
208 int r;
209
210 assert(filename);
211 assert(lvalue);
212 assert(rvalue);
213
214 r = sd_id128_from_string(rvalue, &t);
215 if (r < 0) {
216 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue);
217 return 0;
218 }
219
220 *result = t;
221 return 0;
222 }
223
224 int config_parse_bind(
225 const char *unit,
226 const char *filename,
227 unsigned line,
228 const char *section,
229 unsigned section_line,
230 const char *lvalue,
231 int ltype,
232 const char *rvalue,
233 void *data,
234 void *userdata) {
235
236 Settings *settings = data;
237 int r;
238
239 assert(filename);
240 assert(lvalue);
241 assert(rvalue);
242
243 r = bind_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype);
244 if (r < 0) {
245 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bind mount specification %s: %m", rvalue);
246 return 0;
247 }
248
249 return 0;
250 }
251
252 int config_parse_tmpfs(
253 const char *unit,
254 const char *filename,
255 unsigned line,
256 const char *section,
257 unsigned section_line,
258 const char *lvalue,
259 int ltype,
260 const char *rvalue,
261 void *data,
262 void *userdata) {
263
264 Settings *settings = data;
265 int r;
266
267 assert(filename);
268 assert(lvalue);
269 assert(rvalue);
270
271 r = tmpfs_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue);
272 if (r < 0) {
273 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue);
274 return 0;
275 }
276
277 return 0;
278 }
279
280 int config_parse_veth_extra(
281 const char *unit,
282 const char *filename,
283 unsigned line,
284 const char *section,
285 unsigned section_line,
286 const char *lvalue,
287 int ltype,
288 const char *rvalue,
289 void *data,
290 void *userdata) {
291
292 Settings *settings = data;
293 int r;
294
295 assert(filename);
296 assert(lvalue);
297 assert(rvalue);
298
299 r = veth_extra_parse(&settings->network_veth_extra, rvalue);
300 if (r < 0) {
301 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue);
302 return 0;
303 }
304
305 return 0;
306 }
307
308 int config_parse_boot(
309 const char *unit,
310 const char *filename,
311 unsigned line,
312 const char *section,
313 unsigned section_line,
314 const char *lvalue,
315 int ltype,
316 const char *rvalue,
317 void *data,
318 void *userdata) {
319
320 Settings *settings = data;
321 int r;
322
323 assert(filename);
324 assert(lvalue);
325 assert(rvalue);
326
327 r = parse_boolean(rvalue);
328 if (r < 0) {
329 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue);
330 return 0;
331 }
332
333 if (r > 0) {
334 if (settings->start_mode == START_PID2)
335 goto conflict;
336
337 settings->start_mode = START_BOOT;
338 } else {
339 if (settings->start_mode == START_BOOT)
340 goto conflict;
341
342 if (settings->start_mode < 0)
343 settings->start_mode = START_PID1;
344 }
345
346 return 0;
347
348 conflict:
349 log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
350 return 0;
351 }
352
353 int config_parse_pid2(
354 const char *unit,
355 const char *filename,
356 unsigned line,
357 const char *section,
358 unsigned section_line,
359 const char *lvalue,
360 int ltype,
361 const char *rvalue,
362 void *data,
363 void *userdata) {
364
365 Settings *settings = data;
366 int r;
367
368 assert(filename);
369 assert(lvalue);
370 assert(rvalue);
371
372 r = parse_boolean(rvalue);
373 if (r < 0) {
374 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue);
375 return 0;
376 }
377
378 if (r > 0) {
379 if (settings->start_mode == START_BOOT)
380 goto conflict;
381
382 settings->start_mode = START_PID2;
383 } else {
384 if (settings->start_mode == START_PID2)
385 goto conflict;
386
387 if (settings->start_mode < 0)
388 settings->start_mode = START_PID1;
389 }
390
391 return 0;
392
393 conflict:
394 log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
395 return 0;
396 }