]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
f757855e | 2 | |
b5efdb8a | 3 | #include "alloc-util.h" |
f757855e | 4 | #include "cap-list.h" |
7b3e062c | 5 | #include "conf-parser.h" |
d107bb7d | 6 | #include "cpu-set-util.h" |
3a9530e5 | 7 | #include "hostname-util.h" |
f6d6bad1 | 8 | #include "nspawn-network.h" |
f757855e | 9 | #include "nspawn-settings.h" |
7732f92b | 10 | #include "parse-util.h" |
7b3e062c | 11 | #include "process-util.h" |
bf428efb | 12 | #include "rlimit-util.h" |
22b28dfd | 13 | #include "socket-util.h" |
09d423e9 | 14 | #include "string-table.h" |
22b28dfd | 15 | #include "string-util.h" |
7b3e062c | 16 | #include "strv.h" |
0de7acce | 17 | #include "user-util.h" |
7b3e062c | 18 | #include "util.h" |
f757855e LP |
19 | |
20 | int settings_load(FILE *f, const char *path, Settings **ret) { | |
21 | _cleanup_(settings_freep) Settings *s = NULL; | |
22 | int r; | |
23 | ||
24 | assert(path); | |
25 | assert(ret); | |
26 | ||
27 | s = new0(Settings, 1); | |
28 | if (!s) | |
29 | return -ENOMEM; | |
30 | ||
7732f92b | 31 | s->start_mode = _START_MODE_INVALID; |
f757855e | 32 | s->personality = PERSONALITY_INVALID; |
0de7acce | 33 | s->userns_mode = _USER_NAMESPACE_MODE_INVALID; |
09d423e9 | 34 | s->resolv_conf = _RESOLV_CONF_MODE_INVALID; |
4e1d6aa9 | 35 | s->link_journal = _LINK_JOURNAL_INVALID; |
1688841f | 36 | s->timezone = _TIMEZONE_MODE_INVALID; |
0de7acce LP |
37 | s->uid_shift = UID_INVALID; |
38 | s->uid_range = UID_INVALID; | |
66edd963 | 39 | s->no_new_privileges = -1; |
f757855e LP |
40 | |
41 | s->read_only = -1; | |
42 | s->volatile_mode = _VOLATILE_MODE_INVALID; | |
0de7acce | 43 | s->userns_chown = -1; |
f757855e LP |
44 | |
45 | s->private_network = -1; | |
46 | s->network_veth = -1; | |
47 | ||
48 | r = config_parse(NULL, path, f, | |
49 | "Exec\0" | |
50 | "Network\0" | |
51 | "Files\0", | |
52 | config_item_perf_lookup, nspawn_gperf_lookup, | |
bcde742e | 53 | CONFIG_PARSE_WARN, |
f757855e LP |
54 | s); |
55 | if (r < 0) | |
56 | return r; | |
57 | ||
0de7acce LP |
58 | /* Make sure that if userns_mode is set, userns_chown is set to something appropriate, and vice versa. Either |
59 | * both fields shall be initialized or neither. */ | |
60 | if (s->userns_mode == USER_NAMESPACE_PICK) | |
61 | s->userns_chown = true; | |
62 | else if (s->userns_mode != _USER_NAMESPACE_MODE_INVALID && s->userns_chown < 0) | |
63 | s->userns_chown = false; | |
64 | ||
65 | if (s->userns_chown >= 0 && s->userns_mode == _USER_NAMESPACE_MODE_INVALID) | |
66 | s->userns_mode = USER_NAMESPACE_NO; | |
67 | ||
1cc6c93a | 68 | *ret = TAKE_PTR(s); |
f757855e LP |
69 | |
70 | return 0; | |
71 | } | |
72 | ||
73 | Settings* settings_free(Settings *s) { | |
74 | ||
75 | if (!s) | |
76 | return NULL; | |
77 | ||
78 | strv_free(s->parameters); | |
79 | strv_free(s->environment); | |
80 | free(s->user); | |
b53ede69 PW |
81 | free(s->pivot_root_new); |
82 | free(s->pivot_root_old); | |
5f932eb9 | 83 | free(s->working_directory); |
960e4569 LP |
84 | strv_free(s->syscall_whitelist); |
85 | strv_free(s->syscall_blacklist); | |
bf428efb | 86 | rlimit_free_all(s->rlimit); |
3a9530e5 | 87 | free(s->hostname); |
d107bb7d | 88 | s->cpuset = cpu_set_mfree(s->cpuset); |
f757855e LP |
89 | |
90 | strv_free(s->network_interfaces); | |
91 | strv_free(s->network_macvlan); | |
92 | strv_free(s->network_ipvlan); | |
f6d6bad1 | 93 | strv_free(s->network_veth_extra); |
f757855e | 94 | free(s->network_bridge); |
22b28dfd | 95 | free(s->network_zone); |
f757855e LP |
96 | expose_port_free_all(s->expose_ports); |
97 | ||
98 | custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); | |
6b430fdb | 99 | return mfree(s); |
f757855e LP |
100 | } |
101 | ||
0e265674 LP |
102 | bool settings_private_network(Settings *s) { |
103 | assert(s); | |
104 | ||
105 | return | |
106 | s->private_network > 0 || | |
107 | s->network_veth > 0 || | |
108 | s->network_bridge || | |
22b28dfd | 109 | s->network_zone || |
0e265674 LP |
110 | s->network_interfaces || |
111 | s->network_macvlan || | |
f6d6bad1 LP |
112 | s->network_ipvlan || |
113 | s->network_veth_extra; | |
0e265674 LP |
114 | } |
115 | ||
116 | bool settings_network_veth(Settings *s) { | |
117 | assert(s); | |
118 | ||
119 | return | |
120 | s->network_veth > 0 || | |
22b28dfd LP |
121 | s->network_bridge || |
122 | s->network_zone; | |
0e265674 LP |
123 | } |
124 | ||
f757855e LP |
125 | DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode"); |
126 | ||
127 | int config_parse_expose_port( | |
128 | const char *unit, | |
129 | const char *filename, | |
130 | unsigned line, | |
131 | const char *section, | |
132 | unsigned section_line, | |
133 | const char *lvalue, | |
134 | int ltype, | |
135 | const char *rvalue, | |
136 | void *data, | |
137 | void *userdata) { | |
138 | ||
139 | Settings *s = data; | |
140 | int r; | |
141 | ||
142 | assert(filename); | |
143 | assert(lvalue); | |
144 | assert(rvalue); | |
145 | ||
146 | r = expose_port_parse(&s->expose_ports, rvalue); | |
147 | if (r == -EEXIST) { | |
148 | log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue); | |
149 | return 0; | |
150 | } | |
151 | if (r < 0) { | |
152 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse host port %s: %m", rvalue); | |
153 | return 0; | |
154 | } | |
155 | ||
156 | return 0; | |
157 | } | |
158 | ||
159 | int config_parse_capability( | |
160 | const char *unit, | |
161 | const char *filename, | |
162 | unsigned line, | |
163 | const char *section, | |
164 | unsigned section_line, | |
165 | const char *lvalue, | |
166 | int ltype, | |
167 | const char *rvalue, | |
168 | void *data, | |
169 | void *userdata) { | |
170 | ||
171 | uint64_t u = 0, *result = data; | |
172 | int r; | |
173 | ||
174 | assert(filename); | |
175 | assert(lvalue); | |
176 | assert(rvalue); | |
177 | ||
178 | for (;;) { | |
179 | _cleanup_free_ char *word = NULL; | |
f757855e LP |
180 | |
181 | r = extract_first_word(&rvalue, &word, NULL, 0); | |
182 | if (r < 0) { | |
183 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue); | |
184 | return 0; | |
185 | } | |
186 | if (r == 0) | |
187 | break; | |
188 | ||
acf4d158 YW |
189 | r = capability_from_name(word); |
190 | if (r < 0) { | |
191 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse capability, ignoring: %s", word); | |
f757855e LP |
192 | continue; |
193 | } | |
194 | ||
acf4d158 | 195 | u |= UINT64_C(1) << r; |
f757855e LP |
196 | } |
197 | ||
198 | if (u == 0) | |
199 | return 0; | |
200 | ||
201 | *result |= u; | |
202 | return 0; | |
203 | } | |
204 | ||
205 | int config_parse_id128( | |
206 | const char *unit, | |
207 | const char *filename, | |
208 | unsigned line, | |
209 | const char *section, | |
210 | unsigned section_line, | |
211 | const char *lvalue, | |
212 | int ltype, | |
213 | const char *rvalue, | |
214 | void *data, | |
215 | void *userdata) { | |
216 | ||
217 | sd_id128_t t, *result = data; | |
218 | int r; | |
219 | ||
220 | assert(filename); | |
221 | assert(lvalue); | |
222 | assert(rvalue); | |
223 | ||
224 | r = sd_id128_from_string(rvalue, &t); | |
225 | if (r < 0) { | |
226 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue); | |
227 | return 0; | |
228 | } | |
229 | ||
230 | *result = t; | |
231 | return 0; | |
232 | } | |
233 | ||
b53ede69 PW |
234 | int config_parse_pivot_root( |
235 | const char *unit, | |
236 | const char *filename, | |
237 | unsigned line, | |
238 | const char *section, | |
239 | unsigned section_line, | |
240 | const char *lvalue, | |
241 | int ltype, | |
242 | const char *rvalue, | |
243 | void *data, | |
244 | void *userdata) { | |
245 | ||
246 | Settings *settings = data; | |
247 | int r; | |
248 | ||
249 | assert(filename); | |
250 | assert(lvalue); | |
251 | assert(rvalue); | |
252 | ||
253 | r = pivot_root_parse(&settings->pivot_root_new, &settings->pivot_root_old, rvalue); | |
254 | if (r < 0) { | |
255 | log_syntax(unit, LOG_ERR, filename, line, r, "Invalid pivot root mount specification %s: %m", rvalue); | |
256 | return 0; | |
257 | } | |
258 | ||
259 | return 0; | |
260 | } | |
261 | ||
f757855e LP |
262 | int config_parse_bind( |
263 | const char *unit, | |
264 | const char *filename, | |
265 | unsigned line, | |
266 | const char *section, | |
267 | unsigned section_line, | |
268 | const char *lvalue, | |
269 | int ltype, | |
270 | const char *rvalue, | |
271 | void *data, | |
272 | void *userdata) { | |
273 | ||
274 | Settings *settings = data; | |
275 | int r; | |
276 | ||
277 | assert(filename); | |
278 | assert(lvalue); | |
279 | assert(rvalue); | |
280 | ||
281 | r = bind_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); | |
282 | if (r < 0) { | |
283 | log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bind mount specification %s: %m", rvalue); | |
284 | return 0; | |
285 | } | |
286 | ||
287 | return 0; | |
288 | } | |
289 | ||
290 | int config_parse_tmpfs( | |
291 | const char *unit, | |
292 | const char *filename, | |
293 | unsigned line, | |
294 | const char *section, | |
295 | unsigned section_line, | |
296 | const char *lvalue, | |
297 | int ltype, | |
298 | const char *rvalue, | |
299 | void *data, | |
300 | void *userdata) { | |
301 | ||
302 | Settings *settings = data; | |
303 | int r; | |
304 | ||
305 | assert(filename); | |
306 | assert(lvalue); | |
307 | assert(rvalue); | |
308 | ||
309 | r = tmpfs_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); | |
310 | if (r < 0) { | |
311 | log_syntax(unit, LOG_ERR, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue); | |
312 | return 0; | |
313 | } | |
314 | ||
f6d6bad1 LP |
315 | return 0; |
316 | } | |
f757855e | 317 | |
7b4318b6 LP |
318 | int config_parse_overlay( |
319 | const char *unit, | |
320 | const char *filename, | |
321 | unsigned line, | |
322 | const char *section, | |
323 | unsigned section_line, | |
324 | const char *lvalue, | |
325 | int ltype, | |
326 | const char *rvalue, | |
327 | void *data, | |
328 | void *userdata) { | |
329 | ||
330 | Settings *settings = data; | |
331 | int r; | |
332 | ||
333 | assert(filename); | |
334 | assert(lvalue); | |
335 | assert(rvalue); | |
336 | ||
337 | r = overlay_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); | |
338 | if (r < 0) | |
339 | log_syntax(unit, LOG_ERR, filename, line, r, "Invalid overlay file system specification %s, ignoring: %m", rvalue); | |
340 | ||
341 | return 0; | |
342 | } | |
343 | ||
f6d6bad1 LP |
344 | int config_parse_veth_extra( |
345 | const char *unit, | |
346 | const char *filename, | |
347 | unsigned line, | |
348 | const char *section, | |
349 | unsigned section_line, | |
350 | const char *lvalue, | |
351 | int ltype, | |
352 | const char *rvalue, | |
353 | void *data, | |
354 | void *userdata) { | |
355 | ||
356 | Settings *settings = data; | |
357 | int r; | |
358 | ||
359 | assert(filename); | |
360 | assert(lvalue); | |
361 | assert(rvalue); | |
362 | ||
363 | r = veth_extra_parse(&settings->network_veth_extra, rvalue); | |
364 | if (r < 0) { | |
365 | log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue); | |
366 | return 0; | |
367 | } | |
f757855e LP |
368 | |
369 | return 0; | |
370 | } | |
7732f92b | 371 | |
22b28dfd LP |
372 | int config_parse_network_zone( |
373 | const char *unit, | |
374 | const char *filename, | |
375 | unsigned line, | |
376 | const char *section, | |
377 | unsigned section_line, | |
378 | const char *lvalue, | |
379 | int ltype, | |
380 | const char *rvalue, | |
381 | void *data, | |
382 | void *userdata) { | |
383 | ||
384 | Settings *settings = data; | |
385 | _cleanup_free_ char *j = NULL; | |
386 | ||
387 | assert(filename); | |
388 | assert(lvalue); | |
389 | assert(rvalue); | |
390 | ||
391 | j = strappend("vz-", rvalue); | |
392 | if (!ifname_valid(j)) { | |
c65ac075 | 393 | log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid network zone name, ignoring: %s", rvalue); |
22b28dfd LP |
394 | return 0; |
395 | } | |
396 | ||
f9ecfd3b | 397 | free_and_replace(settings->network_zone, j); |
22b28dfd LP |
398 | |
399 | return 0; | |
400 | } | |
401 | ||
7732f92b LP |
402 | int config_parse_boot( |
403 | const char *unit, | |
404 | const char *filename, | |
405 | unsigned line, | |
406 | const char *section, | |
407 | unsigned section_line, | |
408 | const char *lvalue, | |
409 | int ltype, | |
410 | const char *rvalue, | |
411 | void *data, | |
412 | void *userdata) { | |
413 | ||
414 | Settings *settings = data; | |
415 | int r; | |
416 | ||
417 | assert(filename); | |
418 | assert(lvalue); | |
419 | assert(rvalue); | |
420 | ||
421 | r = parse_boolean(rvalue); | |
422 | if (r < 0) { | |
423 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue); | |
424 | return 0; | |
425 | } | |
426 | ||
427 | if (r > 0) { | |
428 | if (settings->start_mode == START_PID2) | |
429 | goto conflict; | |
430 | ||
431 | settings->start_mode = START_BOOT; | |
432 | } else { | |
433 | if (settings->start_mode == START_BOOT) | |
434 | goto conflict; | |
435 | ||
436 | if (settings->start_mode < 0) | |
437 | settings->start_mode = START_PID1; | |
438 | } | |
439 | ||
440 | return 0; | |
441 | ||
442 | conflict: | |
443 | log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); | |
444 | return 0; | |
445 | } | |
446 | ||
447 | int config_parse_pid2( | |
448 | const char *unit, | |
449 | const char *filename, | |
450 | unsigned line, | |
451 | const char *section, | |
452 | unsigned section_line, | |
453 | const char *lvalue, | |
454 | int ltype, | |
455 | const char *rvalue, | |
456 | void *data, | |
457 | void *userdata) { | |
458 | ||
459 | Settings *settings = data; | |
460 | int r; | |
461 | ||
462 | assert(filename); | |
463 | assert(lvalue); | |
464 | assert(rvalue); | |
465 | ||
466 | r = parse_boolean(rvalue); | |
467 | if (r < 0) { | |
468 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue); | |
469 | return 0; | |
470 | } | |
471 | ||
472 | if (r > 0) { | |
473 | if (settings->start_mode == START_BOOT) | |
474 | goto conflict; | |
475 | ||
476 | settings->start_mode = START_PID2; | |
477 | } else { | |
478 | if (settings->start_mode == START_PID2) | |
479 | goto conflict; | |
480 | ||
481 | if (settings->start_mode < 0) | |
482 | settings->start_mode = START_PID1; | |
483 | } | |
484 | ||
485 | return 0; | |
486 | ||
487 | conflict: | |
488 | log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); | |
489 | return 0; | |
490 | } | |
0de7acce LP |
491 | |
492 | int config_parse_private_users( | |
493 | const char *unit, | |
494 | const char *filename, | |
495 | unsigned line, | |
496 | const char *section, | |
497 | unsigned section_line, | |
498 | const char *lvalue, | |
499 | int ltype, | |
500 | const char *rvalue, | |
501 | void *data, | |
502 | void *userdata) { | |
503 | ||
504 | Settings *settings = data; | |
505 | int r; | |
506 | ||
507 | assert(filename); | |
508 | assert(lvalue); | |
509 | assert(rvalue); | |
510 | ||
511 | r = parse_boolean(rvalue); | |
512 | if (r == 0) { | |
513 | /* no: User namespacing off */ | |
514 | settings->userns_mode = USER_NAMESPACE_NO; | |
515 | settings->uid_shift = UID_INVALID; | |
516 | settings->uid_range = UINT32_C(0x10000); | |
517 | } else if (r > 0) { | |
518 | /* yes: User namespacing on, UID range is read from root dir */ | |
519 | settings->userns_mode = USER_NAMESPACE_FIXED; | |
520 | settings->uid_shift = UID_INVALID; | |
521 | settings->uid_range = UINT32_C(0x10000); | |
522 | } else if (streq(rvalue, "pick")) { | |
523 | /* pick: User namespacing on, UID range is picked randomly */ | |
524 | settings->userns_mode = USER_NAMESPACE_PICK; | |
525 | settings->uid_shift = UID_INVALID; | |
526 | settings->uid_range = UINT32_C(0x10000); | |
527 | } else { | |
528 | const char *range, *shift; | |
529 | uid_t sh, rn; | |
530 | ||
531 | /* anything else: User namespacing on, UID range is explicitly configured */ | |
532 | ||
533 | range = strchr(rvalue, ':'); | |
534 | if (range) { | |
535 | shift = strndupa(rvalue, range - rvalue); | |
536 | range++; | |
537 | ||
538 | r = safe_atou32(range, &rn); | |
539 | if (r < 0 || rn <= 0) { | |
540 | log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID range invalid, ignoring: %s", range); | |
541 | return 0; | |
542 | } | |
543 | } else { | |
544 | shift = rvalue; | |
545 | rn = UINT32_C(0x10000); | |
546 | } | |
547 | ||
548 | r = parse_uid(shift, &sh); | |
549 | if (r < 0) { | |
550 | log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID shift invalid, ignoring: %s", range); | |
551 | return 0; | |
552 | } | |
553 | ||
554 | settings->userns_mode = USER_NAMESPACE_FIXED; | |
555 | settings->uid_shift = sh; | |
556 | settings->uid_range = rn; | |
557 | } | |
558 | ||
559 | return 0; | |
560 | } | |
960e4569 LP |
561 | |
562 | int config_parse_syscall_filter( | |
563 | const char *unit, | |
564 | const char *filename, | |
565 | unsigned line, | |
566 | const char *section, | |
567 | unsigned section_line, | |
568 | const char *lvalue, | |
569 | int ltype, | |
570 | const char *rvalue, | |
571 | void *data, | |
572 | void *userdata) { | |
573 | ||
574 | Settings *settings = data; | |
575 | bool negative; | |
576 | const char *items; | |
577 | int r; | |
578 | ||
579 | assert(filename); | |
580 | assert(lvalue); | |
581 | assert(rvalue); | |
582 | ||
583 | negative = rvalue[0] == '~'; | |
584 | items = negative ? rvalue + 1 : rvalue; | |
585 | ||
586 | for (;;) { | |
587 | _cleanup_free_ char *word = NULL; | |
588 | ||
589 | r = extract_first_word(&items, &word, NULL, 0); | |
590 | if (r == 0) | |
591 | break; | |
592 | if (r == -ENOMEM) | |
593 | return log_oom(); | |
594 | if (r < 0) { | |
595 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue); | |
596 | return 0; | |
597 | } | |
598 | ||
599 | if (negative) | |
600 | r = strv_extend(&settings->syscall_blacklist, word); | |
601 | else | |
602 | r = strv_extend(&settings->syscall_whitelist, word); | |
603 | if (r < 0) | |
604 | return log_oom(); | |
605 | } | |
606 | ||
607 | return 0; | |
608 | } | |
3a9530e5 LP |
609 | |
610 | int config_parse_hostname( | |
611 | const char *unit, | |
612 | const char *filename, | |
613 | unsigned line, | |
614 | const char *section, | |
615 | unsigned section_line, | |
616 | const char *lvalue, | |
617 | int ltype, | |
618 | const char *rvalue, | |
619 | void *data, | |
620 | void *userdata) { | |
621 | ||
622 | char **s = data; | |
623 | ||
624 | assert(rvalue); | |
625 | assert(s); | |
626 | ||
627 | if (!hostname_is_valid(rvalue, false)) { | |
628 | log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue); | |
629 | return 0; | |
630 | } | |
631 | ||
632 | if (free_and_strdup(s, empty_to_null(rvalue)) < 0) | |
633 | return log_oom(); | |
634 | ||
635 | return 0; | |
636 | } | |
81f345df LP |
637 | |
638 | int config_parse_oom_score_adjust( | |
639 | const char *unit, | |
640 | const char *filename, | |
641 | unsigned line, | |
642 | const char *section, | |
643 | unsigned section_line, | |
644 | const char *lvalue, | |
645 | int ltype, | |
646 | const char *rvalue, | |
647 | void *data, | |
648 | void *userdata) { | |
649 | ||
650 | Settings *settings = data; | |
651 | int oa, r; | |
652 | ||
653 | assert(rvalue); | |
654 | assert(settings); | |
655 | ||
656 | if (isempty(rvalue)) { | |
657 | settings->oom_score_adjust_set = false; | |
658 | return 0; | |
659 | } | |
660 | ||
661 | r = parse_oom_score_adjust(rvalue, &oa); | |
662 | if (r == -ERANGE) { | |
663 | log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); | |
664 | return 0; | |
665 | } | |
666 | if (r < 0) { | |
667 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue); | |
668 | return 0; | |
669 | } | |
670 | ||
671 | settings->oom_score_adjust = oa; | |
672 | settings->oom_score_adjust_set = true; | |
673 | ||
674 | return 0; | |
675 | } | |
d107bb7d LP |
676 | |
677 | int config_parse_cpu_affinity( | |
678 | const char *unit, | |
679 | const char *filename, | |
680 | unsigned line, | |
681 | const char *section, | |
682 | unsigned section_line, | |
683 | const char *lvalue, | |
684 | int ltype, | |
685 | const char *rvalue, | |
686 | void *data, | |
687 | void *userdata) { | |
688 | ||
689 | _cleanup_cpu_free_ cpu_set_t *cpuset = NULL; | |
690 | Settings *settings = data; | |
691 | int ncpus; | |
692 | ||
693 | assert(rvalue); | |
694 | assert(settings); | |
695 | ||
696 | ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue); | |
697 | if (ncpus < 0) | |
698 | return ncpus; | |
699 | ||
700 | if (ncpus == 0) { | |
701 | /* An empty assignment resets the CPU list */ | |
702 | settings->cpuset = cpu_set_mfree(settings->cpuset); | |
703 | settings->cpuset_ncpus = 0; | |
704 | return 0; | |
705 | } | |
706 | ||
707 | if (!settings->cpuset) { | |
708 | settings->cpuset = TAKE_PTR(cpuset); | |
709 | settings->cpuset_ncpus = (unsigned) ncpus; | |
710 | return 0; | |
711 | } | |
712 | ||
713 | if (settings->cpuset_ncpus < (unsigned) ncpus) { | |
714 | CPU_OR_S(CPU_ALLOC_SIZE(settings->cpuset_ncpus), cpuset, settings->cpuset, cpuset); | |
715 | CPU_FREE(settings->cpuset); | |
716 | settings->cpuset = TAKE_PTR(cpuset); | |
717 | settings->cpuset_ncpus = (unsigned) ncpus; | |
718 | return 0; | |
719 | } | |
720 | ||
721 | CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), settings->cpuset, settings->cpuset, cpuset); | |
722 | ||
723 | return 0; | |
724 | } | |
09d423e9 LP |
725 | |
726 | DEFINE_CONFIG_PARSE_ENUM(config_parse_resolv_conf, resolv_conf_mode, ResolvConfMode, "Failed to parse resolv.conf mode"); | |
727 | ||
728 | static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = { | |
729 | [RESOLV_CONF_OFF] = "off", | |
730 | [RESOLV_CONF_COPY_HOST] = "copy-host", | |
731 | [RESOLV_CONF_COPY_STATIC] = "copy-static", | |
732 | [RESOLV_CONF_BIND_HOST] = "bind-host", | |
733 | [RESOLV_CONF_BIND_STATIC] = "bind-static", | |
734 | [RESOLV_CONF_DELETE] = "delete", | |
735 | [RESOLV_CONF_AUTO] = "auto", | |
736 | }; | |
737 | ||
738 | DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolv_conf_mode, ResolvConfMode, RESOLV_CONF_AUTO); | |
4e1d6aa9 LP |
739 | |
740 | int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) { | |
741 | assert(s); | |
742 | assert(ret_mode); | |
743 | assert(ret_try); | |
744 | ||
745 | if (streq(s, "auto")) { | |
746 | *ret_mode = LINK_AUTO; | |
747 | *ret_try = false; | |
748 | } else if (streq(s, "no")) { | |
749 | *ret_mode = LINK_NO; | |
750 | *ret_try = false; | |
751 | } else if (streq(s, "guest")) { | |
752 | *ret_mode = LINK_GUEST; | |
753 | *ret_try = false; | |
754 | } else if (streq(s, "host")) { | |
755 | *ret_mode = LINK_HOST; | |
756 | *ret_try = false; | |
757 | } else if (streq(s, "try-guest")) { | |
758 | *ret_mode = LINK_GUEST; | |
759 | *ret_try = true; | |
760 | } else if (streq(s, "try-host")) { | |
761 | *ret_mode = LINK_HOST; | |
762 | *ret_try = true; | |
763 | } else | |
764 | return -EINVAL; | |
765 | ||
766 | return 0; | |
767 | } | |
768 | ||
769 | int config_parse_link_journal( | |
770 | const char *unit, | |
771 | const char *filename, | |
772 | unsigned line, | |
773 | const char *section, | |
774 | unsigned section_line, | |
775 | const char *lvalue, | |
776 | int ltype, | |
777 | const char *rvalue, | |
778 | void *data, | |
779 | void *userdata) { | |
780 | ||
781 | Settings *settings = data; | |
782 | int r; | |
783 | ||
784 | assert(rvalue); | |
785 | assert(settings); | |
786 | ||
787 | r = parse_link_journal(rvalue, &settings->link_journal, &settings->link_journal_try); | |
788 | if (r < 0) { | |
789 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse link journal mode, ignoring: %s", rvalue); | |
790 | return 0; | |
791 | } | |
792 | ||
793 | return 0; | |
794 | } | |
1688841f LP |
795 | |
796 | DEFINE_CONFIG_PARSE_ENUM(config_parse_timezone, timezone_mode, TimezoneMode, "Failed to parse timezone mode"); | |
797 | ||
798 | static const char *const timezone_mode_table[_TIMEZONE_MODE_MAX] = { | |
799 | [TIMEZONE_OFF] = "off", | |
800 | [TIMEZONE_COPY] = "copy", | |
801 | [TIMEZONE_BIND] = "bind", | |
802 | [TIMEZONE_SYMLINK] = "symlink", | |
803 | [TIMEZONE_DELETE] = "delete", | |
804 | [TIMEZONE_AUTO] = "auto", | |
805 | }; | |
806 | ||
807 | DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(timezone_mode, TimezoneMode, TIMEZONE_AUTO); |