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