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