]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/load-fragment.c
2ee4616a1c4686a5c75a61dbacf7e84420240ee5
[thirdparty/systemd.git] / src / core / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2012 Holger Hans Peter Freyther
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <linux/oom.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sched.h>
30 #include <sys/prctl.h>
31 #include <sys/mount.h>
32 #include <linux/fs.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36
37 #ifdef HAVE_SECCOMP
38 #include <seccomp.h>
39 #endif
40
41 #include "sd-messages.h"
42 #include "unit.h"
43 #include "strv.h"
44 #include "conf-parser.h"
45 #include "load-fragment.h"
46 #include "log.h"
47 #include "ioprio.h"
48 #include "securebits.h"
49 #include "missing.h"
50 #include "unit-name.h"
51 #include "unit-printf.h"
52 #include "utf8.h"
53 #include "path-util.h"
54 #include "env-util.h"
55 #include "cgroup.h"
56 #include "bus-util.h"
57 #include "bus-error.h"
58 #include "errno-list.h"
59
60 #ifdef HAVE_SECCOMP
61 #include "seccomp-util.h"
62 #endif
63
64 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP)
65 int config_parse_warn_compat(
66 const char *unit,
67 const char *filename,
68 unsigned line,
69 const char *section,
70 unsigned section_line,
71 const char *lvalue,
72 int ltype,
73 const char *rvalue,
74 void *data,
75 void *userdata) {
76
77 log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
78 "Support for option %s= has been disabled at compile time and is ignored",
79 lvalue);
80 return 0;
81 }
82 #endif
83
84 int config_parse_unit_deps(const char* unit,
85 const char *filename,
86 unsigned line,
87 const char *section,
88 unsigned section_line,
89 const char *lvalue,
90 int ltype,
91 const char *rvalue,
92 void *data,
93 void *userdata) {
94
95 UnitDependency d = ltype;
96 Unit *u = userdata;
97 char *w;
98 size_t l;
99 char *state;
100
101 assert(filename);
102 assert(lvalue);
103 assert(rvalue);
104
105 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
106 _cleanup_free_ char *t = NULL, *k = NULL;
107 int r;
108
109 t = strndup(w, l);
110 if (!t)
111 return log_oom();
112
113 r = unit_name_printf(u, t, &k);
114 if (r < 0) {
115 log_syntax(unit, LOG_ERR, filename, line, -r,
116 "Failed to resolve specifiers, ignoring: %s", strerror(-r));
117 continue;
118 }
119
120 r = unit_add_dependency_by_name(u, d, k, NULL, true);
121 if (r < 0)
122 log_syntax(unit, LOG_ERR, filename, line, -r,
123 "Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
124 }
125
126 return 0;
127 }
128
129 int config_parse_unit_string_printf(const char *unit,
130 const char *filename,
131 unsigned line,
132 const char *section,
133 unsigned section_line,
134 const char *lvalue,
135 int ltype,
136 const char *rvalue,
137 void *data,
138 void *userdata) {
139
140 Unit *u = userdata;
141 _cleanup_free_ char *k = NULL;
142 int r;
143
144 assert(filename);
145 assert(lvalue);
146 assert(rvalue);
147 assert(u);
148
149 r = unit_full_printf(u, rvalue, &k);
150 if (r < 0)
151 log_syntax(unit, LOG_ERR, filename, line, -r,
152 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
153
154 return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
155 k ? k : rvalue, data, userdata);
156 }
157
158 int config_parse_unit_strv_printf(const char *unit,
159 const char *filename,
160 unsigned line,
161 const char *section,
162 unsigned section_line,
163 const char *lvalue,
164 int ltype,
165 const char *rvalue,
166 void *data,
167 void *userdata) {
168
169 Unit *u = userdata;
170 _cleanup_free_ char *k = NULL;
171 int r;
172
173 assert(filename);
174 assert(lvalue);
175 assert(rvalue);
176 assert(u);
177
178 r = unit_full_printf(u, rvalue, &k);
179 if (r < 0)
180 log_syntax(unit, LOG_ERR, filename, line, -r,
181 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
182
183 return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype,
184 k ? k : rvalue, data, userdata);
185 }
186
187 int config_parse_unit_path_printf(const char *unit,
188 const char *filename,
189 unsigned line,
190 const char *section,
191 unsigned section_line,
192 const char *lvalue,
193 int ltype,
194 const char *rvalue,
195 void *data,
196 void *userdata) {
197
198 Unit *u = userdata;
199 _cleanup_free_ char *k = NULL;
200 int r;
201
202 assert(filename);
203 assert(lvalue);
204 assert(rvalue);
205 assert(u);
206
207 r = unit_full_printf(u, rvalue, &k);
208 if (r < 0)
209 log_syntax(unit, LOG_ERR, filename, line, -r,
210 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
211
212 return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype,
213 k ? k : rvalue, data, userdata);
214 }
215
216 int config_parse_socket_listen(const char *unit,
217 const char *filename,
218 unsigned line,
219 const char *section,
220 unsigned section_line,
221 const char *lvalue,
222 int ltype,
223 const char *rvalue,
224 void *data,
225 void *userdata) {
226
227 SocketPort *p, *tail;
228 Socket *s;
229 int r;
230
231 assert(filename);
232 assert(lvalue);
233 assert(rvalue);
234 assert(data);
235
236 s = SOCKET(data);
237
238 if (isempty(rvalue)) {
239 /* An empty assignment removes all ports */
240 socket_free_ports(s);
241 return 0;
242 }
243
244 p = new0(SocketPort, 1);
245 if (!p)
246 return log_oom();
247
248 if (ltype != SOCKET_SOCKET) {
249
250 p->type = ltype;
251 r = unit_full_printf(UNIT(s), rvalue, &p->path);
252 if (r < 0) {
253 p->path = strdup(rvalue);
254 if (!p->path) {
255 free(p);
256 return log_oom();
257 } else
258 log_syntax(unit, LOG_ERR, filename, line, -r,
259 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
260 }
261
262 path_kill_slashes(p->path);
263
264 } else if (streq(lvalue, "ListenNetlink")) {
265 _cleanup_free_ char *k = NULL;
266
267 p->type = SOCKET_SOCKET;
268 r = unit_full_printf(UNIT(s), rvalue, &k);
269 if (r < 0)
270 log_syntax(unit, LOG_ERR, filename, line, -r,
271 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
272
273 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
274 if (r < 0) {
275 log_syntax(unit, LOG_ERR, filename, line, -r,
276 "Failed to parse address value, ignoring: %s", rvalue);
277 free(p);
278 return 0;
279 }
280
281 } else {
282 _cleanup_free_ char *k = NULL;
283
284 p->type = SOCKET_SOCKET;
285 r = unit_full_printf(UNIT(s), rvalue, &k);
286 if (r < 0)
287 log_syntax(unit, LOG_ERR, filename, line, -r,
288 "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
289
290 r = socket_address_parse(&p->address, k ? k : rvalue);
291 if (r < 0) {
292 log_syntax(unit, LOG_ERR, filename, line, -r,
293 "Failed to parse address value, ignoring: %s", rvalue);
294 free(p);
295 return 0;
296 }
297
298 if (streq(lvalue, "ListenStream"))
299 p->address.type = SOCK_STREAM;
300 else if (streq(lvalue, "ListenDatagram"))
301 p->address.type = SOCK_DGRAM;
302 else {
303 assert(streq(lvalue, "ListenSequentialPacket"));
304 p->address.type = SOCK_SEQPACKET;
305 }
306
307 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
308 log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
309 "Address family not supported, ignoring: %s", rvalue);
310 free(p);
311 return 0;
312 }
313 }
314
315 p->fd = -1;
316 p->socket = s;
317
318 if (s->ports) {
319 LIST_FIND_TAIL(port, s->ports, tail);
320 LIST_INSERT_AFTER(port, s->ports, tail, p);
321 } else
322 LIST_PREPEND(port, s->ports, p);
323
324 return 0;
325 }
326
327 int config_parse_socket_bind(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 Socket *s;
339 SocketAddressBindIPv6Only b;
340
341 assert(filename);
342 assert(lvalue);
343 assert(rvalue);
344 assert(data);
345
346 s = SOCKET(data);
347
348 b = socket_address_bind_ipv6_only_from_string(rvalue);
349 if (b < 0) {
350 int r;
351
352 r = parse_boolean(rvalue);
353 if (r < 0) {
354 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
355 "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
356 return 0;
357 }
358
359 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
360 } else
361 s->bind_ipv6_only = b;
362
363 return 0;
364 }
365
366 int config_parse_exec_nice(const char *unit,
367 const char *filename,
368 unsigned line,
369 const char *section,
370 unsigned section_line,
371 const char *lvalue,
372 int ltype,
373 const char *rvalue,
374 void *data,
375 void *userdata) {
376
377 ExecContext *c = data;
378 int priority, r;
379
380 assert(filename);
381 assert(lvalue);
382 assert(rvalue);
383 assert(data);
384
385 r = safe_atoi(rvalue, &priority);
386 if (r < 0) {
387 log_syntax(unit, LOG_ERR, filename, line, -r,
388 "Failed to parse nice priority, ignoring: %s. ", rvalue);
389 return 0;
390 }
391
392 if (priority < PRIO_MIN || priority >= PRIO_MAX) {
393 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
394 "Nice priority out of range, ignoring: %s", rvalue);
395 return 0;
396 }
397
398 c->nice = priority;
399 c->nice_set = true;
400
401 return 0;
402 }
403
404 int config_parse_exec_oom_score_adjust(const char* unit,
405 const char *filename,
406 unsigned line,
407 const char *section,
408 unsigned section_line,
409 const char *lvalue,
410 int ltype,
411 const char *rvalue,
412 void *data,
413 void *userdata) {
414
415 ExecContext *c = data;
416 int oa, r;
417
418 assert(filename);
419 assert(lvalue);
420 assert(rvalue);
421 assert(data);
422
423 r = safe_atoi(rvalue, &oa);
424 if (r < 0) {
425 log_syntax(unit, LOG_ERR, filename, line, -r,
426 "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
427 return 0;
428 }
429
430 if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
431 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
432 "OOM score adjust value out of range, ignoring: %s", rvalue);
433 return 0;
434 }
435
436 c->oom_score_adjust = oa;
437 c->oom_score_adjust_set = true;
438
439 return 0;
440 }
441
442 int config_parse_exec(const char *unit,
443 const char *filename,
444 unsigned line,
445 const char *section,
446 unsigned section_line,
447 const char *lvalue,
448 int ltype,
449 const char *rvalue,
450 void *data,
451 void *userdata) {
452
453 ExecCommand **e = data, *nce;
454 char *path, **n;
455 unsigned k;
456 int r;
457
458 assert(filename);
459 assert(lvalue);
460 assert(rvalue);
461 assert(e);
462
463 e += ltype;
464
465 if (isempty(rvalue)) {
466 /* An empty assignment resets the list */
467 exec_command_free_list(*e);
468 *e = NULL;
469 return 0;
470 }
471
472 /* We accept an absolute path as first argument, or
473 * alternatively an absolute prefixed with @ to allow
474 * overriding of argv[0]. */
475 for (;;) {
476 int i;
477 char *w;
478 size_t l;
479 char *state;
480 bool honour_argv0 = false, ignore = false;
481
482 path = NULL;
483 nce = NULL;
484 n = NULL;
485
486 rvalue += strspn(rvalue, WHITESPACE);
487
488 if (rvalue[0] == 0)
489 break;
490
491 for (i = 0; i < 2; i++) {
492 if (rvalue[0] == '-' && !ignore) {
493 ignore = true;
494 rvalue ++;
495 }
496
497 if (rvalue[0] == '@' && !honour_argv0) {
498 honour_argv0 = true;
499 rvalue ++;
500 }
501 }
502
503 if (*rvalue != '/') {
504 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
505 "Executable path is not absolute, ignoring: %s", rvalue);
506 return 0;
507 }
508
509 k = 0;
510 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
511 if (strneq(w, ";", MAX(l, 1U)))
512 break;
513
514 k++;
515 }
516
517 n = new(char*, k + !honour_argv0);
518 if (!n)
519 return log_oom();
520
521 k = 0;
522 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
523 if (strneq(w, ";", MAX(l, 1U)))
524 break;
525 else if (strneq(w, "\\;", MAX(l, 1U)))
526 w ++;
527
528 if (honour_argv0 && w == rvalue) {
529 assert(!path);
530
531 path = strndup(w, l);
532 if (!path) {
533 r = log_oom();
534 goto fail;
535 }
536
537 if (!utf8_is_valid(path)) {
538 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
539 "Path is not UTF-8 clean, ignoring assignment: %s",
540 rvalue);
541 r = 0;
542 goto fail;
543 }
544
545 } else {
546 char *c;
547
548 c = n[k++] = cunescape_length(w, l);
549 if (!c) {
550 r = log_oom();
551 goto fail;
552 }
553
554 if (!utf8_is_valid(c)) {
555 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
556 "Path is not UTF-8 clean, ignoring assignment: %s",
557 rvalue);
558 r = 0;
559 goto fail;
560 }
561 }
562 }
563
564 n[k] = NULL;
565
566 if (!n[0]) {
567 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
568 "Invalid command line, ignoring: %s", rvalue);
569 r = 0;
570 goto fail;
571 }
572
573 if (!path) {
574 path = strdup(n[0]);
575 if (!path) {
576 r = log_oom();
577 goto fail;
578 }
579 }
580
581 assert(path_is_absolute(path));
582
583 nce = new0(ExecCommand, 1);
584 if (!nce) {
585 r = log_oom();
586 goto fail;
587 }
588
589 nce->argv = n;
590 nce->path = path;
591 nce->ignore = ignore;
592
593 path_kill_slashes(nce->path);
594
595 exec_command_append_list(e, nce);
596
597 rvalue = state;
598 }
599
600 return 0;
601
602 fail:
603 n[k] = NULL;
604 strv_free(n);
605 free(path);
606 free(nce);
607
608 return r;
609 }
610
611 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
612 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
613
614 int config_parse_socket_bindtodevice(const char* unit,
615 const char *filename,
616 unsigned line,
617 const char *section,
618 unsigned section_line,
619 const char *lvalue,
620 int ltype,
621 const char *rvalue,
622 void *data,
623 void *userdata) {
624
625 Socket *s = data;
626 char *n;
627
628 assert(filename);
629 assert(lvalue);
630 assert(rvalue);
631 assert(data);
632
633 if (rvalue[0] && !streq(rvalue, "*")) {
634 n = strdup(rvalue);
635 if (!n)
636 return log_oom();
637 } else
638 n = NULL;
639
640 free(s->bind_to_device);
641 s->bind_to_device = n;
642
643 return 0;
644 }
645
646 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
647 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
648
649 int config_parse_exec_io_class(const char *unit,
650 const char *filename,
651 unsigned line,
652 const char *section,
653 unsigned section_line,
654 const char *lvalue,
655 int ltype,
656 const char *rvalue,
657 void *data,
658 void *userdata) {
659
660 ExecContext *c = data;
661 int x;
662
663 assert(filename);
664 assert(lvalue);
665 assert(rvalue);
666 assert(data);
667
668 x = ioprio_class_from_string(rvalue);
669 if (x < 0) {
670 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
671 "Failed to parse IO scheduling class, ignoring: %s", rvalue);
672 return 0;
673 }
674
675 c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
676 c->ioprio_set = true;
677
678 return 0;
679 }
680
681 int config_parse_exec_io_priority(const char *unit,
682 const char *filename,
683 unsigned line,
684 const char *section,
685 unsigned section_line,
686 const char *lvalue,
687 int ltype,
688 const char *rvalue,
689 void *data,
690 void *userdata) {
691
692 ExecContext *c = data;
693 int i, r;
694
695 assert(filename);
696 assert(lvalue);
697 assert(rvalue);
698 assert(data);
699
700 r = safe_atoi(rvalue, &i);
701 if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
702 log_syntax(unit, LOG_ERR, filename, line, -r,
703 "Failed to parse IO priority, ignoring: %s", rvalue);
704 return 0;
705 }
706
707 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
708 c->ioprio_set = true;
709
710 return 0;
711 }
712
713 int config_parse_exec_cpu_sched_policy(const char *unit,
714 const char *filename,
715 unsigned line,
716 const char *section,
717 unsigned section_line,
718 const char *lvalue,
719 int ltype,
720 const char *rvalue,
721 void *data,
722 void *userdata) {
723
724
725 ExecContext *c = data;
726 int x;
727
728 assert(filename);
729 assert(lvalue);
730 assert(rvalue);
731 assert(data);
732
733 x = sched_policy_from_string(rvalue);
734 if (x < 0) {
735 log_syntax(unit, LOG_ERR, filename, line, -x,
736 "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
737 return 0;
738 }
739
740 c->cpu_sched_policy = x;
741 /* Moving to or from real-time policy? We need to adjust the priority */
742 c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
743 c->cpu_sched_set = true;
744
745 return 0;
746 }
747
748 int config_parse_exec_cpu_sched_prio(const char *unit,
749 const char *filename,
750 unsigned line,
751 const char *section,
752 unsigned section_line,
753 const char *lvalue,
754 int ltype,
755 const char *rvalue,
756 void *data,
757 void *userdata) {
758
759 ExecContext *c = data;
760 int i, min, max, r;
761
762 assert(filename);
763 assert(lvalue);
764 assert(rvalue);
765 assert(data);
766
767 r = safe_atoi(rvalue, &i);
768 if (r < 0) {
769 log_syntax(unit, LOG_ERR, filename, line, -r,
770 "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
771 return 0;
772 }
773
774 /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
775 min = sched_get_priority_min(c->cpu_sched_policy);
776 max = sched_get_priority_max(c->cpu_sched_policy);
777
778 if (i < min || i > max) {
779 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
780 "CPU scheduling priority is out of range, ignoring: %s", rvalue);
781 return 0;
782 }
783
784 c->cpu_sched_priority = i;
785 c->cpu_sched_set = true;
786
787 return 0;
788 }
789
790 int config_parse_exec_cpu_affinity(const char *unit,
791 const char *filename,
792 unsigned line,
793 const char *section,
794 unsigned section_line,
795 const char *lvalue,
796 int ltype,
797 const char *rvalue,
798 void *data,
799 void *userdata) {
800
801 ExecContext *c = data;
802 char *w;
803 size_t l;
804 char *state;
805
806 assert(filename);
807 assert(lvalue);
808 assert(rvalue);
809 assert(data);
810
811 if (isempty(rvalue)) {
812 /* An empty assignment resets the CPU list */
813 if (c->cpuset)
814 CPU_FREE(c->cpuset);
815 c->cpuset = NULL;
816 return 0;
817 }
818
819 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
820 _cleanup_free_ char *t = NULL;
821 int r;
822 unsigned cpu;
823
824 t = strndup(w, l);
825 if (!t)
826 return log_oom();
827
828 r = safe_atou(t, &cpu);
829
830 if (!c->cpuset) {
831 c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
832 if (!c->cpuset)
833 return log_oom();
834 }
835
836 if (r < 0 || cpu >= c->cpuset_ncpus) {
837 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
838 "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
839 return 0;
840 }
841
842 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
843 }
844
845 return 0;
846 }
847
848 int config_parse_exec_capabilities(const char *unit,
849 const char *filename,
850 unsigned line,
851 const char *section,
852 unsigned section_line,
853 const char *lvalue,
854 int ltype,
855 const char *rvalue,
856 void *data,
857 void *userdata) {
858
859 ExecContext *c = data;
860 cap_t cap;
861
862 assert(filename);
863 assert(lvalue);
864 assert(rvalue);
865 assert(data);
866
867 cap = cap_from_text(rvalue);
868 if (!cap) {
869 log_syntax(unit, LOG_ERR, filename, line, errno,
870 "Failed to parse capabilities, ignoring: %s", rvalue);
871 return 0;
872 }
873
874 if (c->capabilities)
875 cap_free(c->capabilities);
876 c->capabilities = cap;
877
878 return 0;
879 }
880
881 int config_parse_exec_secure_bits(const char *unit,
882 const char *filename,
883 unsigned line,
884 const char *section,
885 unsigned section_line,
886 const char *lvalue,
887 int ltype,
888 const char *rvalue,
889 void *data,
890 void *userdata) {
891
892 ExecContext *c = data;
893 char *w;
894 size_t l;
895 char *state;
896
897 assert(filename);
898 assert(lvalue);
899 assert(rvalue);
900 assert(data);
901
902 if (isempty(rvalue)) {
903 /* An empty assignment resets the field */
904 c->secure_bits = 0;
905 return 0;
906 }
907
908 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
909 if (first_word(w, "keep-caps"))
910 c->secure_bits |= 1<<SECURE_KEEP_CAPS;
911 else if (first_word(w, "keep-caps-locked"))
912 c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
913 else if (first_word(w, "no-setuid-fixup"))
914 c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
915 else if (first_word(w, "no-setuid-fixup-locked"))
916 c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
917 else if (first_word(w, "noroot"))
918 c->secure_bits |= 1<<SECURE_NOROOT;
919 else if (first_word(w, "noroot-locked"))
920 c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
921 else {
922 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
923 "Failed to parse secure bits, ignoring: %s", rvalue);
924 return 0;
925 }
926 }
927
928 return 0;
929 }
930
931 int config_parse_bounding_set(const char *unit,
932 const char *filename,
933 unsigned line,
934 const char *section,
935 unsigned section_line,
936 const char *lvalue,
937 int ltype,
938 const char *rvalue,
939 void *data,
940 void *userdata) {
941
942 uint64_t *capability_bounding_set_drop = data;
943 char *w;
944 size_t l;
945 char *state;
946 bool invert = false;
947 uint64_t sum = 0;
948
949 assert(filename);
950 assert(lvalue);
951 assert(rvalue);
952 assert(data);
953
954 if (rvalue[0] == '~') {
955 invert = true;
956 rvalue++;
957 }
958
959 /* Note that we store this inverted internally, since the
960 * kernel wants it like this. But we actually expose it
961 * non-inverted everywhere to have a fully normalized
962 * interface. */
963
964 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
965 _cleanup_free_ char *t = NULL;
966 int r;
967 cap_value_t cap;
968
969 t = strndup(w, l);
970 if (!t)
971 return log_oom();
972
973 r = cap_from_name(t, &cap);
974 if (r < 0) {
975 log_syntax(unit, LOG_ERR, filename, line, errno,
976 "Failed to parse capability in bounding set, ignoring: %s", t);
977 continue;
978 }
979
980 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
981 }
982
983 if (invert)
984 *capability_bounding_set_drop |= sum;
985 else
986 *capability_bounding_set_drop |= ~sum;
987
988 return 0;
989 }
990
991 int config_parse_limit(const char *unit,
992 const char *filename,
993 unsigned line,
994 const char *section,
995 unsigned section_line,
996 const char *lvalue,
997 int ltype,
998 const char *rvalue,
999 void *data,
1000 void *userdata) {
1001
1002 struct rlimit **rl = data;
1003 unsigned long long u;
1004
1005 assert(filename);
1006 assert(lvalue);
1007 assert(rvalue);
1008 assert(data);
1009
1010 rl += ltype;
1011
1012 if (streq(rvalue, "infinity"))
1013 u = (unsigned long long) RLIM_INFINITY;
1014 else {
1015 int r;
1016
1017 r = safe_atollu(rvalue, &u);
1018 if (r < 0) {
1019 log_syntax(unit, LOG_ERR, filename, line, -r,
1020 "Failed to parse resource value, ignoring: %s", rvalue);
1021 return 0;
1022 }
1023 }
1024
1025 if (!*rl) {
1026 *rl = new(struct rlimit, 1);
1027 if (!*rl)
1028 return log_oom();
1029 }
1030
1031 (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
1032 return 0;
1033 }
1034
1035 #ifdef HAVE_SYSV_COMPAT
1036 int config_parse_sysv_priority(const char *unit,
1037 const char *filename,
1038 unsigned line,
1039 const char *section,
1040 unsigned section_line,
1041 const char *lvalue,
1042 int ltype,
1043 const char *rvalue,
1044 void *data,
1045 void *userdata) {
1046
1047 int *priority = data;
1048 int i, r;
1049
1050 assert(filename);
1051 assert(lvalue);
1052 assert(rvalue);
1053 assert(data);
1054
1055 r = safe_atoi(rvalue, &i);
1056 if (r < 0 || i < 0) {
1057 log_syntax(unit, LOG_ERR, filename, line, -r,
1058 "Failed to parse SysV start priority, ignoring: %s", rvalue);
1059 return 0;
1060 }
1061
1062 *priority = (int) i;
1063 return 0;
1064 }
1065 #endif
1066
1067 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1068
1069 int config_parse_kill_signal(const char *unit,
1070 const char *filename,
1071 unsigned line,
1072 const char *section,
1073 unsigned section_line,
1074 const char *lvalue,
1075 int ltype,
1076 const char *rvalue,
1077 void *data,
1078 void *userdata) {
1079
1080 int *sig = data;
1081 int r;
1082
1083 assert(filename);
1084 assert(lvalue);
1085 assert(rvalue);
1086 assert(sig);
1087
1088 r = signal_from_string_try_harder(rvalue);
1089 if (r <= 0) {
1090 log_syntax(unit, LOG_ERR, filename, line, -r,
1091 "Failed to parse kill signal, ignoring: %s", rvalue);
1092 return 0;
1093 }
1094
1095 *sig = r;
1096 return 0;
1097 }
1098
1099 int config_parse_exec_mount_flags(const char *unit,
1100 const char *filename,
1101 unsigned line,
1102 const char *section,
1103 unsigned section_line,
1104 const char *lvalue,
1105 int ltype,
1106 const char *rvalue,
1107 void *data,
1108 void *userdata) {
1109
1110 ExecContext *c = data;
1111 char *w;
1112 size_t l;
1113 char *state;
1114 unsigned long flags = 0;
1115
1116 assert(filename);
1117 assert(lvalue);
1118 assert(rvalue);
1119 assert(data);
1120
1121 FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1122 _cleanup_free_ char *t;
1123
1124 t = strndup(w, l);
1125 if (!t)
1126 return log_oom();
1127
1128 if (streq(t, "shared"))
1129 flags |= MS_SHARED;
1130 else if (streq(t, "slave"))
1131 flags |= MS_SLAVE;
1132 else if (streq(w, "private"))
1133 flags |= MS_PRIVATE;
1134 else {
1135 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1136 "Failed to parse mount flag %s, ignoring: %s",
1137 t, rvalue);
1138 return 0;
1139 }
1140 }
1141
1142 c->mount_flags = flags;
1143 return 0;
1144 }
1145
1146 int config_parse_exec_selinux_context(
1147 const char *unit,
1148 const char *filename,
1149 unsigned line,
1150 const char *section,
1151 unsigned section_line,
1152 const char *lvalue,
1153 int ltype,
1154 const char *rvalue,
1155 void *data,
1156 void *userdata) {
1157
1158 ExecContext *c = data;
1159 Unit *u = userdata;
1160 bool ignore;
1161 char *k;
1162 int r;
1163
1164 assert(filename);
1165 assert(lvalue);
1166 assert(rvalue);
1167 assert(data);
1168
1169 if (isempty(rvalue)) {
1170 free(c->selinux_context);
1171 c->selinux_context = NULL;
1172 c->selinux_context_ignore = false;
1173 return 0;
1174 }
1175
1176 if (rvalue[0] == '-') {
1177 ignore = true;
1178 rvalue++;
1179 } else
1180 ignore = false;
1181
1182 r = unit_name_printf(u, rvalue, &k);
1183 if (r < 0) {
1184 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1185 return 0;
1186 }
1187
1188 free(c->selinux_context);
1189 c->selinux_context = k;
1190 c->selinux_context_ignore = ignore;
1191
1192 return 0;
1193 }
1194
1195 int config_parse_timer(const char *unit,
1196 const char *filename,
1197 unsigned line,
1198 const char *section,
1199 unsigned section_line,
1200 const char *lvalue,
1201 int ltype,
1202 const char *rvalue,
1203 void *data,
1204 void *userdata) {
1205
1206 Timer *t = data;
1207 usec_t u = 0;
1208 TimerValue *v;
1209 TimerBase b;
1210 CalendarSpec *c = NULL;
1211 clockid_t id;
1212
1213 assert(filename);
1214 assert(lvalue);
1215 assert(rvalue);
1216 assert(data);
1217
1218 if (isempty(rvalue)) {
1219 /* Empty assignment resets list */
1220 timer_free_values(t);
1221 return 0;
1222 }
1223
1224 b = timer_base_from_string(lvalue);
1225 if (b < 0) {
1226 log_syntax(unit, LOG_ERR, filename, line, -b,
1227 "Failed to parse timer base, ignoring: %s", lvalue);
1228 return 0;
1229 }
1230
1231 if (b == TIMER_CALENDAR) {
1232 if (calendar_spec_from_string(rvalue, &c) < 0) {
1233 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1234 "Failed to parse calendar specification, ignoring: %s",
1235 rvalue);
1236 return 0;
1237 }
1238
1239 id = CLOCK_REALTIME;
1240 } else {
1241 if (parse_sec(rvalue, &u) < 0) {
1242 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1243 "Failed to parse timer value, ignoring: %s",
1244 rvalue);
1245 return 0;
1246 }
1247
1248 id = CLOCK_MONOTONIC;
1249 }
1250
1251 v = new0(TimerValue, 1);
1252 if (!v)
1253 return log_oom();
1254
1255 v->base = b;
1256 v->clock_id = id;
1257 v->value = u;
1258 v->calendar_spec = c;
1259
1260 LIST_PREPEND(value, t->values, v);
1261
1262 return 0;
1263 }
1264
1265 int config_parse_trigger_unit(
1266 const char *unit,
1267 const char *filename,
1268 unsigned line,
1269 const char *section,
1270 unsigned section_line,
1271 const char *lvalue,
1272 int ltype,
1273 const char *rvalue,
1274 void *data,
1275 void *userdata) {
1276
1277 _cleanup_free_ char *p = NULL;
1278 Unit *u = data;
1279 UnitType type;
1280 int r;
1281
1282 assert(filename);
1283 assert(lvalue);
1284 assert(rvalue);
1285 assert(data);
1286
1287 if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1288 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1289 "Multiple units to trigger specified, ignoring: %s", rvalue);
1290 return 0;
1291 }
1292
1293 r = unit_name_printf(u, rvalue, &p);
1294 if (r < 0)
1295 log_syntax(unit, LOG_ERR, filename, line, -r,
1296 "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1297
1298 type = unit_name_to_type(p ?: rvalue);
1299 if (type < 0) {
1300 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1301 "Unit type not valid, ignoring: %s", rvalue);
1302 return 0;
1303 }
1304
1305 if (type == u->type) {
1306 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1307 "Trigger cannot be of same type, ignoring: %s", rvalue);
1308 return 0;
1309 }
1310
1311 r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1312 if (r < 0) {
1313 log_syntax(unit, LOG_ERR, filename, line, -r,
1314 "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1315 return 0;
1316 }
1317
1318 return 0;
1319 }
1320
1321 int config_parse_path_spec(const char *unit,
1322 const char *filename,
1323 unsigned line,
1324 const char *section,
1325 unsigned section_line,
1326 const char *lvalue,
1327 int ltype,
1328 const char *rvalue,
1329 void *data,
1330 void *userdata) {
1331
1332 Path *p = data;
1333 PathSpec *s;
1334 PathType b;
1335 _cleanup_free_ char *k = NULL;
1336 int r;
1337
1338 assert(filename);
1339 assert(lvalue);
1340 assert(rvalue);
1341 assert(data);
1342
1343 if (isempty(rvalue)) {
1344 /* Empty assignment clears list */
1345 path_free_specs(p);
1346 return 0;
1347 }
1348
1349 b = path_type_from_string(lvalue);
1350 if (b < 0) {
1351 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1352 "Failed to parse path type, ignoring: %s", lvalue);
1353 return 0;
1354 }
1355
1356 r = unit_full_printf(UNIT(p), rvalue, &k);
1357 if (r < 0) {
1358 k = strdup(rvalue);
1359 if (!k)
1360 return log_oom();
1361 else
1362 log_syntax(unit, LOG_ERR, filename, line, -r,
1363 "Failed to resolve unit specifiers on %s. Ignoring.",
1364 rvalue);
1365 }
1366
1367 if (!path_is_absolute(k)) {
1368 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1369 "Path is not absolute, ignoring: %s", k);
1370 return 0;
1371 }
1372
1373 s = new0(PathSpec, 1);
1374 if (!s)
1375 return log_oom();
1376
1377 s->unit = UNIT(p);
1378 s->path = path_kill_slashes(k);
1379 k = NULL;
1380 s->type = b;
1381 s->inotify_fd = -1;
1382
1383 LIST_PREPEND(spec, p->specs, s);
1384
1385 return 0;
1386 }
1387
1388 int config_parse_socket_service(const char *unit,
1389 const char *filename,
1390 unsigned line,
1391 const char *section,
1392 unsigned section_line,
1393 const char *lvalue,
1394 int ltype,
1395 const char *rvalue,
1396 void *data,
1397 void *userdata) {
1398
1399 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1400 Socket *s = data;
1401 int r;
1402 Unit *x;
1403 _cleanup_free_ char *p = NULL;
1404
1405 assert(filename);
1406 assert(lvalue);
1407 assert(rvalue);
1408 assert(data);
1409
1410 r = unit_name_printf(UNIT(s), rvalue, &p);
1411 if (r < 0) {
1412 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1413 return 0;
1414 }
1415
1416 if (!endswith(p, ".service")) {
1417 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1418 return 0;
1419 }
1420
1421 r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1422 if (r < 0) {
1423 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1424 return 0;
1425 }
1426
1427 unit_ref_set(&s->service, x);
1428
1429 return 0;
1430 }
1431
1432 int config_parse_service_sockets(const char *unit,
1433 const char *filename,
1434 unsigned line,
1435 const char *section,
1436 unsigned section_line,
1437 const char *lvalue,
1438 int ltype,
1439 const char *rvalue,
1440 void *data,
1441 void *userdata) {
1442
1443 Service *s = data;
1444 int r;
1445 char *state, *w;
1446 size_t l;
1447
1448 assert(filename);
1449 assert(lvalue);
1450 assert(rvalue);
1451 assert(data);
1452
1453 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1454 _cleanup_free_ char *t = NULL, *k = NULL;
1455
1456 t = strndup(w, l);
1457 if (!t)
1458 return log_oom();
1459
1460 r = unit_name_printf(UNIT(s), t, &k);
1461 if (r < 0)
1462 log_syntax(unit, LOG_ERR, filename, line, -r,
1463 "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1464
1465 if (!endswith(k ?: t, ".socket")) {
1466 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1467 "Unit must be of type socket, ignoring: %s", k ?: t);
1468 continue;
1469 }
1470
1471 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1472 if (r < 0)
1473 log_syntax(unit, LOG_ERR, filename, line, -r,
1474 "Failed to add dependency on %s, ignoring: %s",
1475 k ?: t, strerror(-r));
1476
1477 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1478 if (r < 0)
1479 return r;
1480 }
1481
1482 return 0;
1483 }
1484
1485 int config_parse_service_timeout(const char *unit,
1486 const char *filename,
1487 unsigned line,
1488 const char *section,
1489 unsigned section_line,
1490 const char *lvalue,
1491 int ltype,
1492 const char *rvalue,
1493 void *data,
1494 void *userdata) {
1495
1496 Service *s = userdata;
1497 int r;
1498
1499 assert(filename);
1500 assert(lvalue);
1501 assert(rvalue);
1502 assert(s);
1503
1504 r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1505 rvalue, data, userdata);
1506 if (r < 0)
1507 return r;
1508
1509 if (streq(lvalue, "TimeoutSec")) {
1510 s->start_timeout_defined = true;
1511 s->timeout_stop_usec = s->timeout_start_usec;
1512 } else if (streq(lvalue, "TimeoutStartSec"))
1513 s->start_timeout_defined = true;
1514
1515 return 0;
1516 }
1517
1518 int config_parse_busname_service(
1519 const char *unit,
1520 const char *filename,
1521 unsigned line,
1522 const char *section,
1523 unsigned section_line,
1524 const char *lvalue,
1525 int ltype,
1526 const char *rvalue,
1527 void *data,
1528 void *userdata) {
1529
1530 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1531 BusName *n = data;
1532 int r;
1533 Unit *x;
1534 _cleanup_free_ char *p = NULL;
1535
1536 assert(filename);
1537 assert(lvalue);
1538 assert(rvalue);
1539 assert(data);
1540
1541 r = unit_name_printf(UNIT(n), rvalue, &p);
1542 if (r < 0) {
1543 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1544 return 0;
1545 }
1546
1547 if (!endswith(p, ".service")) {
1548 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1549 return 0;
1550 }
1551
1552 r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1553 if (r < 0) {
1554 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1555 return 0;
1556 }
1557
1558 unit_ref_set(&n->service, x);
1559
1560 return 0;
1561 }
1562
1563 int config_parse_unit_env_file(const char *unit,
1564 const char *filename,
1565 unsigned line,
1566 const char *section,
1567 unsigned section_line,
1568 const char *lvalue,
1569 int ltype,
1570 const char *rvalue,
1571 void *data,
1572 void *userdata) {
1573
1574 char ***env = data;
1575 Unit *u = userdata;
1576 _cleanup_free_ char *n = NULL;
1577 const char *s;
1578 int r;
1579
1580 assert(filename);
1581 assert(lvalue);
1582 assert(rvalue);
1583 assert(data);
1584
1585 if (isempty(rvalue)) {
1586 /* Empty assignment frees the list */
1587 strv_free(*env);
1588 *env = NULL;
1589 return 0;
1590 }
1591
1592 r = unit_full_printf(u, rvalue, &n);
1593 if (r < 0)
1594 log_syntax(unit, LOG_ERR, filename, line, r,
1595 "Failed to resolve specifiers, ignoring: %s", rvalue);
1596
1597 s = n ?: rvalue;
1598 if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1599 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1600 "Path '%s' is not absolute, ignoring.", s);
1601 return 0;
1602 }
1603
1604 r = strv_extend(env, s);
1605 if (r < 0)
1606 return log_oom();
1607
1608 return 0;
1609 }
1610
1611 int config_parse_environ(const char *unit,
1612 const char *filename,
1613 unsigned line,
1614 const char *section,
1615 unsigned section_line,
1616 const char *lvalue,
1617 int ltype,
1618 const char *rvalue,
1619 void *data,
1620 void *userdata) {
1621
1622 Unit *u = userdata;
1623 char*** env = data, *w, *state;
1624 size_t l;
1625 _cleanup_free_ char *k = NULL;
1626 int r;
1627
1628 assert(filename);
1629 assert(lvalue);
1630 assert(rvalue);
1631 assert(data);
1632
1633 if (isempty(rvalue)) {
1634 /* Empty assignment resets the list */
1635 strv_free(*env);
1636 *env = NULL;
1637 return 0;
1638 }
1639
1640 if (u) {
1641 r = unit_full_printf(u, rvalue, &k);
1642 if (r < 0)
1643 log_syntax(unit, LOG_ERR, filename, line, -r,
1644 "Failed to resolve specifiers, ignoring: %s", rvalue);
1645 }
1646
1647 if (!k)
1648 k = strdup(rvalue);
1649 if (!k)
1650 return log_oom();
1651
1652 FOREACH_WORD_QUOTED(w, l, k, state) {
1653 _cleanup_free_ char *n;
1654 char **x;
1655
1656 n = cunescape_length(w, l);
1657 if (!n)
1658 return log_oom();
1659
1660 if (!env_assignment_is_valid(n)) {
1661 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1662 "Invalid environment assignment, ignoring: %s", rvalue);
1663 continue;
1664 }
1665
1666 x = strv_env_set(*env, n);
1667 if (!x)
1668 return log_oom();
1669
1670 strv_free(*env);
1671 *env = x;
1672 }
1673
1674 return 0;
1675 }
1676
1677 int config_parse_ip_tos(const char *unit,
1678 const char *filename,
1679 unsigned line,
1680 const char *section,
1681 unsigned section_line,
1682 const char *lvalue,
1683 int ltype,
1684 const char *rvalue,
1685 void *data,
1686 void *userdata) {
1687
1688 int *ip_tos = data, x;
1689
1690 assert(filename);
1691 assert(lvalue);
1692 assert(rvalue);
1693 assert(data);
1694
1695 x = ip_tos_from_string(rvalue);
1696 if (x < 0) {
1697 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1698 "Failed to parse IP TOS value, ignoring: %s", rvalue);
1699 return 0;
1700 }
1701
1702 *ip_tos = x;
1703 return 0;
1704 }
1705
1706 int config_parse_unit_condition_path(const char *unit,
1707 const char *filename,
1708 unsigned line,
1709 const char *section,
1710 unsigned section_line,
1711 const char *lvalue,
1712 int ltype,
1713 const char *rvalue,
1714 void *data,
1715 void *userdata) {
1716
1717 ConditionType cond = ltype;
1718 Unit *u = data;
1719 bool trigger, negate;
1720 Condition *c;
1721 _cleanup_free_ char *p = NULL;
1722 int r;
1723
1724 assert(filename);
1725 assert(lvalue);
1726 assert(rvalue);
1727 assert(data);
1728
1729 if (isempty(rvalue)) {
1730 /* Empty assignment resets the list */
1731 condition_free_list(u->conditions);
1732 u->conditions = NULL;
1733 return 0;
1734 }
1735
1736 trigger = rvalue[0] == '|';
1737 if (trigger)
1738 rvalue++;
1739
1740 negate = rvalue[0] == '!';
1741 if (negate)
1742 rvalue++;
1743
1744 r = unit_full_printf(u, rvalue, &p);
1745 if (r < 0)
1746 log_syntax(unit, LOG_ERR, filename, line, -r,
1747 "Failed to resolve specifiers, ignoring: %s", rvalue);
1748 if (!p) {
1749 p = strdup(rvalue);
1750 if (!p)
1751 return log_oom();
1752 }
1753
1754 if (!path_is_absolute(p)) {
1755 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1756 "Path in condition not absolute, ignoring: %s", p);
1757 return 0;
1758 }
1759
1760 c = condition_new(cond, p, trigger, negate);
1761 if (!c)
1762 return log_oom();
1763
1764 LIST_PREPEND(conditions, u->conditions, c);
1765 return 0;
1766 }
1767
1768 int config_parse_unit_condition_string(const char *unit,
1769 const char *filename,
1770 unsigned line,
1771 const char *section,
1772 unsigned section_line,
1773 const char *lvalue,
1774 int ltype,
1775 const char *rvalue,
1776 void *data,
1777 void *userdata) {
1778
1779 ConditionType cond = ltype;
1780 Unit *u = data;
1781 bool trigger, negate;
1782 Condition *c;
1783 _cleanup_free_ char *s = NULL;
1784 int r;
1785
1786 assert(filename);
1787 assert(lvalue);
1788 assert(rvalue);
1789 assert(data);
1790
1791 if (isempty(rvalue)) {
1792 /* Empty assignment resets the list */
1793 condition_free_list(u->conditions);
1794 u->conditions = NULL;
1795 return 0;
1796 }
1797
1798 trigger = rvalue[0] == '|';
1799 if (trigger)
1800 rvalue++;
1801
1802 negate = rvalue[0] == '!';
1803 if (negate)
1804 rvalue++;
1805
1806 r = unit_full_printf(u, rvalue, &s);
1807 if (r < 0)
1808 log_syntax(unit, LOG_ERR, filename, line, -r,
1809 "Failed to resolve specifiers, ignoring: %s", rvalue);
1810 if (!s) {
1811 s = strdup(rvalue);
1812 if (!s)
1813 return log_oom();
1814 }
1815
1816 c = condition_new(cond, s, trigger, negate);
1817 if (!c)
1818 return log_oom();
1819
1820 LIST_PREPEND(conditions, u->conditions, c);
1821 return 0;
1822 }
1823
1824 int config_parse_unit_condition_null(const char *unit,
1825 const char *filename,
1826 unsigned line,
1827 const char *section,
1828 unsigned section_line,
1829 const char *lvalue,
1830 int ltype,
1831 const char *rvalue,
1832 void *data,
1833 void *userdata) {
1834
1835 Unit *u = data;
1836 Condition *c;
1837 bool trigger, negate;
1838 int b;
1839
1840 assert(filename);
1841 assert(lvalue);
1842 assert(rvalue);
1843 assert(data);
1844
1845 if (isempty(rvalue)) {
1846 /* Empty assignment resets the list */
1847 condition_free_list(u->conditions);
1848 u->conditions = NULL;
1849 return 0;
1850 }
1851
1852 trigger = rvalue[0] == '|';
1853 if (trigger)
1854 rvalue++;
1855
1856 negate = rvalue[0] == '!';
1857 if (negate)
1858 rvalue++;
1859
1860 b = parse_boolean(rvalue);
1861 if (b < 0) {
1862 log_syntax(unit, LOG_ERR, filename, line, -b,
1863 "Failed to parse boolean value in condition, ignoring: %s",
1864 rvalue);
1865 return 0;
1866 }
1867
1868 if (!b)
1869 negate = !negate;
1870
1871 c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1872 if (!c)
1873 return log_oom();
1874
1875 LIST_PREPEND(conditions, u->conditions, c);
1876 return 0;
1877 }
1878
1879 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1880 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
1881
1882 int config_parse_unit_requires_mounts_for(
1883 const char *unit,
1884 const char *filename,
1885 unsigned line,
1886 const char *section,
1887 unsigned section_line,
1888 const char *lvalue,
1889 int ltype,
1890 const char *rvalue,
1891 void *data,
1892 void *userdata) {
1893
1894 Unit *u = userdata;
1895 char *state;
1896 size_t l;
1897 char *w;
1898
1899 assert(filename);
1900 assert(lvalue);
1901 assert(rvalue);
1902 assert(data);
1903
1904 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1905 int r;
1906 _cleanup_free_ char *n;
1907
1908 n = strndup(w, l);
1909 if (!n)
1910 return log_oom();
1911
1912 if (!utf8_is_valid(n)) {
1913 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1914 "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
1915 continue;
1916 }
1917
1918 r = unit_require_mounts_for(u, n);
1919 if (r < 0) {
1920 log_syntax(unit, LOG_ERR, filename, line, r,
1921 "Failed to add required mount for, ignoring: %s", rvalue);
1922 continue;
1923 }
1924 }
1925
1926 return 0;
1927 }
1928
1929 int config_parse_documentation(const char *unit,
1930 const char *filename,
1931 unsigned line,
1932 const char *section,
1933 unsigned section_line,
1934 const char *lvalue,
1935 int ltype,
1936 const char *rvalue,
1937 void *data,
1938 void *userdata) {
1939
1940 Unit *u = userdata;
1941 int r;
1942 char **a, **b;
1943
1944 assert(filename);
1945 assert(lvalue);
1946 assert(rvalue);
1947 assert(u);
1948
1949 if (isempty(rvalue)) {
1950 /* Empty assignment resets the list */
1951 strv_free(u->documentation);
1952 u->documentation = NULL;
1953 return 0;
1954 }
1955
1956 r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
1957 rvalue, data, userdata);
1958 if (r < 0)
1959 return r;
1960
1961 for (a = b = u->documentation; a && *a; a++) {
1962
1963 if (is_valid_documentation_url(*a))
1964 *(b++) = *a;
1965 else {
1966 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1967 "Invalid URL, ignoring: %s", *a);
1968 free(*a);
1969 }
1970 }
1971 if (b)
1972 *b = NULL;
1973
1974 return r;
1975 }
1976
1977 #ifdef HAVE_SECCOMP
1978 int config_parse_syscall_filter(
1979 const char *unit,
1980 const char *filename,
1981 unsigned line,
1982 const char *section,
1983 unsigned section_line,
1984 const char *lvalue,
1985 int ltype,
1986 const char *rvalue,
1987 void *data,
1988 void *userdata) {
1989
1990 static const char default_syscalls[] =
1991 "execve\0"
1992 "exit\0"
1993 "exit_group\0"
1994 "rt_sigreturn\0"
1995 "sigreturn\0";
1996
1997 ExecContext *c = data;
1998 Unit *u = userdata;
1999 bool invert = false;
2000 char *w, *state;
2001 size_t l;
2002 int r;
2003
2004 assert(filename);
2005 assert(lvalue);
2006 assert(rvalue);
2007 assert(u);
2008
2009 if (isempty(rvalue)) {
2010 /* Empty assignment resets the list */
2011 set_free(c->syscall_filter);
2012 c->syscall_filter = NULL;
2013 c->syscall_whitelist = false;
2014 return 0;
2015 }
2016
2017 if (rvalue[0] == '~') {
2018 invert = true;
2019 rvalue++;
2020 }
2021
2022 if (!c->syscall_filter) {
2023 c->syscall_filter = set_new(trivial_hash_func, trivial_compare_func);
2024 if (!c->syscall_filter)
2025 return log_oom();
2026
2027 if (invert)
2028 /* Allow everything but the ones listed */
2029 c->syscall_whitelist = false;
2030 else {
2031 const char *i;
2032
2033 /* Allow nothing but the ones listed */
2034 c->syscall_whitelist = true;
2035
2036 /* Accept default syscalls if we are on a whitelist */
2037 NULSTR_FOREACH(i, default_syscalls) {
2038 int id;
2039
2040 id = seccomp_syscall_resolve_name(i);
2041 if (id < 0)
2042 continue;
2043
2044 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2045 if (r == -EEXIST)
2046 continue;
2047 if (r < 0)
2048 return log_oom();
2049 }
2050 }
2051 }
2052
2053 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2054 _cleanup_free_ char *t = NULL;
2055 int id;
2056
2057 t = strndup(w, l);
2058 if (!t)
2059 return log_oom();
2060
2061 id = seccomp_syscall_resolve_name(t);
2062 if (id < 0) {
2063 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call, ignoring: %s", t);
2064 continue;
2065 }
2066
2067 /* If we previously wanted to forbid a syscall and now
2068 * we want to allow it, then remove it from the list
2069 */
2070 if (!invert == c->syscall_whitelist) {
2071 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2072 if (r == -EEXIST)
2073 continue;
2074 if (r < 0)
2075 return log_oom();
2076 } else
2077 set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
2078 }
2079
2080 c->no_new_privileges = true;
2081
2082 return 0;
2083 }
2084
2085 int config_parse_syscall_archs(
2086 const char *unit,
2087 const char *filename,
2088 unsigned line,
2089 const char *section,
2090 unsigned section_line,
2091 const char *lvalue,
2092 int ltype,
2093 const char *rvalue,
2094 void *data,
2095 void *userdata) {
2096
2097 Set **archs = data;
2098 char *w, *state;
2099 size_t l;
2100 int r;
2101
2102 if (isempty(rvalue)) {
2103 set_free(*archs);
2104 *archs = NULL;
2105 return 0;
2106 }
2107
2108 r = set_ensure_allocated(archs, trivial_hash_func, trivial_compare_func);
2109 if (r < 0)
2110 return log_oom();
2111
2112 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2113 _cleanup_free_ char *t = NULL;
2114 uint32_t a;
2115
2116 t = strndup(w, l);
2117 if (!t)
2118 return log_oom();
2119
2120 r = seccomp_arch_from_string(t, &a);
2121 if (r < 0) {
2122 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call architecture, ignoring: %s", t);
2123 continue;
2124 }
2125
2126 r = set_put(*archs, UINT32_TO_PTR(a + 1));
2127 if (r == -EEXIST)
2128 continue;
2129 if (r < 0)
2130 return log_oom();
2131 }
2132
2133 return 0;
2134 }
2135
2136 int config_parse_syscall_errno(
2137 const char *unit,
2138 const char *filename,
2139 unsigned line,
2140 const char *section,
2141 unsigned section_line,
2142 const char *lvalue,
2143 int ltype,
2144 const char *rvalue,
2145 void *data,
2146 void *userdata) {
2147
2148 ExecContext *c = data;
2149 int e;
2150
2151 assert(filename);
2152 assert(lvalue);
2153 assert(rvalue);
2154
2155 if (isempty(rvalue)) {
2156 /* Empty assignment resets to KILL */
2157 c->syscall_errno = 0;
2158 return 0;
2159 }
2160
2161 e = errno_from_name(rvalue);
2162 if (e < 0) {
2163 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse error number, ignoring: %s", rvalue);
2164 return 0;
2165 }
2166
2167 c->syscall_errno = e;
2168 return 0;
2169 }
2170 #endif
2171
2172 int config_parse_unit_slice(
2173 const char *unit,
2174 const char *filename,
2175 unsigned line,
2176 const char *section,
2177 unsigned section_line,
2178 const char *lvalue,
2179 int ltype,
2180 const char *rvalue,
2181 void *data,
2182 void *userdata) {
2183
2184 _cleanup_free_ char *k = NULL;
2185 Unit *u = userdata, *slice;
2186 int r;
2187
2188 assert(filename);
2189 assert(lvalue);
2190 assert(rvalue);
2191 assert(u);
2192
2193 r = unit_name_printf(u, rvalue, &k);
2194 if (r < 0)
2195 log_syntax(unit, LOG_ERR, filename, line, -r,
2196 "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2197 if (!k) {
2198 k = strdup(rvalue);
2199 if (!k)
2200 return log_oom();
2201 }
2202
2203 r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2204 if (r < 0) {
2205 log_syntax(unit, LOG_ERR, filename, line, -r,
2206 "Failed to load slice unit %s. Ignoring.", k);
2207 return 0;
2208 }
2209
2210 if (slice->type != UNIT_SLICE) {
2211 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2212 "Slice unit %s is not a slice. Ignoring.", k);
2213 return 0;
2214 }
2215
2216 unit_ref_set(&u->slice, slice);
2217 return 0;
2218 }
2219
2220 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2221
2222 int config_parse_cpu_shares(
2223 const char *unit,
2224 const char *filename,
2225 unsigned line,
2226 const char *section,
2227 unsigned section_line,
2228 const char *lvalue,
2229 int ltype,
2230 const char *rvalue,
2231 void *data,
2232 void *userdata) {
2233
2234 CGroupContext *c = data;
2235 unsigned long lu;
2236 int r;
2237
2238 assert(filename);
2239 assert(lvalue);
2240 assert(rvalue);
2241
2242 if (isempty(rvalue)) {
2243 c->cpu_shares = 1024;
2244 return 0;
2245 }
2246
2247 r = safe_atolu(rvalue, &lu);
2248 if (r < 0 || lu <= 0) {
2249 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2250 "CPU shares '%s' invalid. Ignoring.", rvalue);
2251 return 0;
2252 }
2253
2254 c->cpu_shares = lu;
2255 return 0;
2256 }
2257
2258 int config_parse_memory_limit(
2259 const char *unit,
2260 const char *filename,
2261 unsigned line,
2262 const char *section,
2263 unsigned section_line,
2264 const char *lvalue,
2265 int ltype,
2266 const char *rvalue,
2267 void *data,
2268 void *userdata) {
2269
2270 CGroupContext *c = data;
2271 off_t bytes;
2272 int r;
2273
2274 if (isempty(rvalue)) {
2275 c->memory_limit = (uint64_t) -1;
2276 return 0;
2277 }
2278
2279 assert_cc(sizeof(uint64_t) == sizeof(off_t));
2280
2281 r = parse_bytes(rvalue, &bytes);
2282 if (r < 0) {
2283 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2284 "Memory limit '%s' invalid. Ignoring.", rvalue);
2285 return 0;
2286 }
2287
2288 c->memory_limit = (uint64_t) bytes;
2289 return 0;
2290 }
2291
2292 int config_parse_device_allow(
2293 const char *unit,
2294 const char *filename,
2295 unsigned line,
2296 const char *section,
2297 unsigned section_line,
2298 const char *lvalue,
2299 int ltype,
2300 const char *rvalue,
2301 void *data,
2302 void *userdata) {
2303
2304 _cleanup_free_ char *path = NULL;
2305 CGroupContext *c = data;
2306 CGroupDeviceAllow *a;
2307 const char *m;
2308 size_t n;
2309
2310 if (isempty(rvalue)) {
2311 while (c->device_allow)
2312 cgroup_context_free_device_allow(c, c->device_allow);
2313
2314 return 0;
2315 }
2316
2317 n = strcspn(rvalue, WHITESPACE);
2318 path = strndup(rvalue, n);
2319 if (!path)
2320 return log_oom();
2321
2322 if (!path_startswith(path, "/dev")) {
2323 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2324 "Invalid device node path '%s'. Ignoring.", path);
2325 return 0;
2326 }
2327
2328 m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2329 if (isempty(m))
2330 m = "rwm";
2331
2332 if (!in_charset(m, "rwm")) {
2333 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2334 "Invalid device rights '%s'. Ignoring.", m);
2335 return 0;
2336 }
2337
2338 a = new0(CGroupDeviceAllow, 1);
2339 if (!a)
2340 return log_oom();
2341
2342 a->path = path;
2343 path = NULL;
2344 a->r = !!strchr(m, 'r');
2345 a->w = !!strchr(m, 'w');
2346 a->m = !!strchr(m, 'm');
2347
2348 LIST_PREPEND(device_allow, c->device_allow, a);
2349 return 0;
2350 }
2351
2352 int config_parse_blockio_weight(
2353 const char *unit,
2354 const char *filename,
2355 unsigned line,
2356 const char *section,
2357 unsigned section_line,
2358 const char *lvalue,
2359 int ltype,
2360 const char *rvalue,
2361 void *data,
2362 void *userdata) {
2363
2364 CGroupContext *c = data;
2365 unsigned long lu;
2366 int r;
2367
2368 assert(filename);
2369 assert(lvalue);
2370 assert(rvalue);
2371
2372 if (isempty(rvalue)) {
2373 c->blockio_weight = 1000;
2374 return 0;
2375 }
2376
2377 r = safe_atolu(rvalue, &lu);
2378 if (r < 0 || lu < 10 || lu > 1000) {
2379 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2380 "Block IO weight '%s' invalid. Ignoring.", rvalue);
2381 return 0;
2382 }
2383
2384 c->blockio_weight = lu;
2385
2386 return 0;
2387 }
2388
2389 int config_parse_blockio_device_weight(
2390 const char *unit,
2391 const char *filename,
2392 unsigned line,
2393 const char *section,
2394 unsigned section_line,
2395 const char *lvalue,
2396 int ltype,
2397 const char *rvalue,
2398 void *data,
2399 void *userdata) {
2400
2401 _cleanup_free_ char *path = NULL;
2402 CGroupBlockIODeviceWeight *w;
2403 CGroupContext *c = data;
2404 unsigned long lu;
2405 const char *weight;
2406 size_t n;
2407 int r;
2408
2409 assert(filename);
2410 assert(lvalue);
2411 assert(rvalue);
2412
2413 if (isempty(rvalue)) {
2414 while (c->blockio_device_weights)
2415 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2416
2417 return 0;
2418 }
2419
2420 n = strcspn(rvalue, WHITESPACE);
2421 weight = rvalue + n;
2422 if (!*weight) {
2423 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2424 "Expected block device and device weight. Ignoring.");
2425 return 0;
2426 }
2427
2428 path = strndup(rvalue, n);
2429 if (!path)
2430 return log_oom();
2431
2432 if (!path_startswith(path, "/dev")) {
2433 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2434 "Invalid device node path '%s'. Ignoring.", path);
2435 return 0;
2436 }
2437
2438 weight += strspn(weight, WHITESPACE);
2439 r = safe_atolu(weight, &lu);
2440 if (r < 0 || lu < 10 || lu > 1000) {
2441 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2442 "Block IO weight '%s' invalid. Ignoring.", rvalue);
2443 return 0;
2444 }
2445
2446
2447 w = new0(CGroupBlockIODeviceWeight, 1);
2448 if (!w)
2449 return log_oom();
2450
2451 w->path = path;
2452 path = NULL;
2453
2454 w->weight = lu;
2455
2456 LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2457 return 0;
2458 }
2459
2460 int config_parse_blockio_bandwidth(
2461 const char *unit,
2462 const char *filename,
2463 unsigned line,
2464 const char *section,
2465 unsigned section_line,
2466 const char *lvalue,
2467 int ltype,
2468 const char *rvalue,
2469 void *data,
2470 void *userdata) {
2471
2472 _cleanup_free_ char *path = NULL;
2473 CGroupBlockIODeviceBandwidth *b;
2474 CGroupContext *c = data;
2475 const char *bandwidth;
2476 off_t bytes;
2477 bool read;
2478 size_t n;
2479 int r;
2480
2481 assert(filename);
2482 assert(lvalue);
2483 assert(rvalue);
2484
2485 read = streq("BlockIOReadBandwidth", lvalue);
2486
2487 if (isempty(rvalue)) {
2488 CGroupBlockIODeviceBandwidth *next;
2489
2490 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2491 if (b->read == read)
2492 cgroup_context_free_blockio_device_bandwidth(c, b);
2493
2494 return 0;
2495 }
2496
2497 n = strcspn(rvalue, WHITESPACE);
2498 bandwidth = rvalue + n;
2499 bandwidth += strspn(bandwidth, WHITESPACE);
2500
2501 if (!*bandwidth) {
2502 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2503 "Expected space separated pair of device node and bandwidth. Ignoring.");
2504 return 0;
2505 }
2506
2507 path = strndup(rvalue, n);
2508 if (!path)
2509 return log_oom();
2510
2511 if (!path_startswith(path, "/dev")) {
2512 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2513 "Invalid device node path '%s'. Ignoring.", path);
2514 return 0;
2515 }
2516
2517 r = parse_bytes(bandwidth, &bytes);
2518 if (r < 0 || bytes <= 0) {
2519 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2520 "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2521 return 0;
2522 }
2523
2524 b = new0(CGroupBlockIODeviceBandwidth, 1);
2525 if (!b)
2526 return log_oom();
2527
2528 b->path = path;
2529 path = NULL;
2530 b->bandwidth = (uint64_t) bytes;
2531 b->read = read;
2532
2533 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2534
2535 return 0;
2536 }
2537
2538 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
2539
2540 int config_parse_job_mode_isolate(
2541 const char *unit,
2542 const char *filename,
2543 unsigned line,
2544 const char *section,
2545 unsigned section_line,
2546 const char *lvalue,
2547 int ltype,
2548 const char *rvalue,
2549 void *data,
2550 void *userdata) {
2551
2552 JobMode *m = data;
2553 int r;
2554
2555 assert(filename);
2556 assert(lvalue);
2557 assert(rvalue);
2558
2559 r = parse_boolean(rvalue);
2560 if (r < 0) {
2561 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse boolean, ignoring: %s", rvalue);
2562 return 0;
2563 }
2564
2565 *m = r ? JOB_ISOLATE : JOB_REPLACE;
2566 return 0;
2567 }
2568
2569 #define FOLLOW_MAX 8
2570
2571 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2572 unsigned c = 0;
2573 int fd, r;
2574 FILE *f;
2575 char *id = NULL;
2576
2577 assert(filename);
2578 assert(*filename);
2579 assert(_f);
2580 assert(names);
2581
2582 /* This will update the filename pointer if the loaded file is
2583 * reached by a symlink. The old string will be freed. */
2584
2585 for (;;) {
2586 char *target, *name;
2587
2588 if (c++ >= FOLLOW_MAX)
2589 return -ELOOP;
2590
2591 path_kill_slashes(*filename);
2592
2593 /* Add the file name we are currently looking at to
2594 * the names of this unit, but only if it is a valid
2595 * unit name. */
2596 name = basename(*filename);
2597
2598 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
2599
2600 id = set_get(names, name);
2601 if (!id) {
2602 id = strdup(name);
2603 if (!id)
2604 return -ENOMEM;
2605
2606 r = set_consume(names, id);
2607 if (r < 0)
2608 return r;
2609 }
2610 }
2611
2612 /* Try to open the file name, but don't if its a symlink */
2613 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2614 if (fd >= 0)
2615 break;
2616
2617 if (errno != ELOOP)
2618 return -errno;
2619
2620 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2621 r = readlink_and_make_absolute(*filename, &target);
2622 if (r < 0)
2623 return r;
2624
2625 free(*filename);
2626 *filename = target;
2627 }
2628
2629 f = fdopen(fd, "re");
2630 if (!f) {
2631 r = -errno;
2632 close_nointr_nofail(fd);
2633 return r;
2634 }
2635
2636 *_f = f;
2637 *_final = id;
2638 return 0;
2639 }
2640
2641 static int merge_by_names(Unit **u, Set *names, const char *id) {
2642 char *k;
2643 int r;
2644
2645 assert(u);
2646 assert(*u);
2647 assert(names);
2648
2649 /* Let's try to add in all symlink names we found */
2650 while ((k = set_steal_first(names))) {
2651
2652 /* First try to merge in the other name into our
2653 * unit */
2654 r = unit_merge_by_name(*u, k);
2655 if (r < 0) {
2656 Unit *other;
2657
2658 /* Hmm, we couldn't merge the other unit into
2659 * ours? Then let's try it the other way
2660 * round */
2661
2662 other = manager_get_unit((*u)->manager, k);
2663 free(k);
2664
2665 if (other) {
2666 r = unit_merge(other, *u);
2667 if (r >= 0) {
2668 *u = other;
2669 return merge_by_names(u, names, NULL);
2670 }
2671 }
2672
2673 return r;
2674 }
2675
2676 if (id == k)
2677 unit_choose_id(*u, id);
2678
2679 free(k);
2680 }
2681
2682 return 0;
2683 }
2684
2685 static int load_from_path(Unit *u, const char *path) {
2686 int r;
2687 _cleanup_set_free_free_ Set *symlink_names = NULL;
2688 _cleanup_fclose_ FILE *f = NULL;
2689 _cleanup_free_ char *filename = NULL;
2690 char *id = NULL;
2691 Unit *merged;
2692 struct stat st;
2693
2694 assert(u);
2695 assert(path);
2696
2697 symlink_names = set_new(string_hash_func, string_compare_func);
2698 if (!symlink_names)
2699 return -ENOMEM;
2700
2701 if (path_is_absolute(path)) {
2702
2703 filename = strdup(path);
2704 if (!filename)
2705 return -ENOMEM;
2706
2707 r = open_follow(&filename, &f, symlink_names, &id);
2708 if (r < 0) {
2709 free(filename);
2710 filename = NULL;
2711
2712 if (r != -ENOENT)
2713 return r;
2714 }
2715
2716 } else {
2717 char **p;
2718
2719 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2720
2721 /* Instead of opening the path right away, we manually
2722 * follow all symlinks and add their name to our unit
2723 * name set while doing so */
2724 filename = path_make_absolute(path, *p);
2725 if (!filename)
2726 return -ENOMEM;
2727
2728 if (u->manager->unit_path_cache &&
2729 !set_get(u->manager->unit_path_cache, filename))
2730 r = -ENOENT;
2731 else
2732 r = open_follow(&filename, &f, symlink_names, &id);
2733
2734 if (r < 0) {
2735 free(filename);
2736 filename = NULL;
2737
2738 if (r != -ENOENT)
2739 return r;
2740
2741 /* Empty the symlink names for the next run */
2742 set_clear_free(symlink_names);
2743 continue;
2744 }
2745
2746 break;
2747 }
2748 }
2749
2750 if (!filename)
2751 /* Hmm, no suitable file found? */
2752 return 0;
2753
2754 merged = u;
2755 r = merge_by_names(&merged, symlink_names, id);
2756 if (r < 0)
2757 return r;
2758
2759 if (merged != u) {
2760 u->load_state = UNIT_MERGED;
2761 return 0;
2762 }
2763
2764 if (fstat(fileno(f), &st) < 0)
2765 return -errno;
2766
2767 if (null_or_empty(&st))
2768 u->load_state = UNIT_MASKED;
2769 else {
2770 u->load_state = UNIT_LOADED;
2771
2772 /* Now, parse the file contents */
2773 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
2774 config_item_perf_lookup,
2775 (void*) load_fragment_gperf_lookup, false, true, u);
2776 if (r < 0)
2777 return r;
2778 }
2779
2780 free(u->fragment_path);
2781 u->fragment_path = filename;
2782 filename = NULL;
2783
2784 u->fragment_mtime = timespec_load(&st.st_mtim);
2785
2786 if (u->source_path) {
2787 if (stat(u->source_path, &st) >= 0)
2788 u->source_mtime = timespec_load(&st.st_mtim);
2789 else
2790 u->source_mtime = 0;
2791 }
2792
2793 return 0;
2794 }
2795
2796 int unit_load_fragment(Unit *u) {
2797 int r;
2798 Iterator i;
2799 const char *t;
2800
2801 assert(u);
2802 assert(u->load_state == UNIT_STUB);
2803 assert(u->id);
2804
2805 /* First, try to find the unit under its id. We always look
2806 * for unit files in the default directories, to make it easy
2807 * to override things by placing things in /etc/systemd/system */
2808 r = load_from_path(u, u->id);
2809 if (r < 0)
2810 return r;
2811
2812 /* Try to find an alias we can load this with */
2813 if (u->load_state == UNIT_STUB)
2814 SET_FOREACH(t, u->names, i) {
2815
2816 if (t == u->id)
2817 continue;
2818
2819 r = load_from_path(u, t);
2820 if (r < 0)
2821 return r;
2822
2823 if (u->load_state != UNIT_STUB)
2824 break;
2825 }
2826
2827 /* And now, try looking for it under the suggested (originally linked) path */
2828 if (u->load_state == UNIT_STUB && u->fragment_path) {
2829
2830 r = load_from_path(u, u->fragment_path);
2831 if (r < 0)
2832 return r;
2833
2834 if (u->load_state == UNIT_STUB) {
2835 /* Hmm, this didn't work? Then let's get rid
2836 * of the fragment path stored for us, so that
2837 * we don't point to an invalid location. */
2838 free(u->fragment_path);
2839 u->fragment_path = NULL;
2840 }
2841 }
2842
2843 /* Look for a template */
2844 if (u->load_state == UNIT_STUB && u->instance) {
2845 _cleanup_free_ char *k;
2846
2847 k = unit_name_template(u->id);
2848 if (!k)
2849 return -ENOMEM;
2850
2851 r = load_from_path(u, k);
2852 if (r < 0)
2853 return r;
2854
2855 if (u->load_state == UNIT_STUB)
2856 SET_FOREACH(t, u->names, i) {
2857 _cleanup_free_ char *z = NULL;
2858
2859 if (t == u->id)
2860 continue;
2861
2862 z = unit_name_template(t);
2863 if (!z)
2864 return -ENOMEM;
2865
2866 r = load_from_path(u, z);
2867 if (r < 0)
2868 return r;
2869
2870 if (u->load_state != UNIT_STUB)
2871 break;
2872 }
2873 }
2874
2875 return 0;
2876 }
2877
2878 void unit_dump_config_items(FILE *f) {
2879 static const struct {
2880 const ConfigParserCallback callback;
2881 const char *rvalue;
2882 } table[] = {
2883 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP)
2884 { config_parse_warn_compat, "NOTSUPPORTED" },
2885 #endif
2886 { config_parse_int, "INTEGER" },
2887 { config_parse_unsigned, "UNSIGNED" },
2888 { config_parse_bytes_size, "SIZE" },
2889 { config_parse_bool, "BOOLEAN" },
2890 { config_parse_string, "STRING" },
2891 { config_parse_path, "PATH" },
2892 { config_parse_unit_path_printf, "PATH" },
2893 { config_parse_strv, "STRING [...]" },
2894 { config_parse_exec_nice, "NICE" },
2895 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2896 { config_parse_exec_io_class, "IOCLASS" },
2897 { config_parse_exec_io_priority, "IOPRIORITY" },
2898 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2899 { config_parse_exec_cpu_sched_prio, "CPUSCHEDPRIO" },
2900 { config_parse_exec_cpu_affinity, "CPUAFFINITY" },
2901 { config_parse_mode, "MODE" },
2902 { config_parse_unit_env_file, "FILE" },
2903 { config_parse_output, "OUTPUT" },
2904 { config_parse_input, "INPUT" },
2905 { config_parse_facility, "FACILITY" },
2906 { config_parse_level, "LEVEL" },
2907 { config_parse_exec_capabilities, "CAPABILITIES" },
2908 { config_parse_exec_secure_bits, "SECUREBITS" },
2909 { config_parse_bounding_set, "BOUNDINGSET" },
2910 { config_parse_limit, "LIMIT" },
2911 { config_parse_unit_deps, "UNIT [...]" },
2912 { config_parse_exec, "PATH [ARGUMENT [...]]" },
2913 { config_parse_service_type, "SERVICETYPE" },
2914 { config_parse_service_restart, "SERVICERESTART" },
2915 #ifdef HAVE_SYSV_COMPAT
2916 { config_parse_sysv_priority, "SYSVPRIORITY" },
2917 #endif
2918 { config_parse_kill_mode, "KILLMODE" },
2919 { config_parse_kill_signal, "SIGNAL" },
2920 { config_parse_socket_listen, "SOCKET [...]" },
2921 { config_parse_socket_bind, "SOCKETBIND" },
2922 { config_parse_socket_bindtodevice, "NETWORKINTERFACE" },
2923 { config_parse_sec, "SECONDS" },
2924 { config_parse_nsec, "NANOSECONDS" },
2925 { config_parse_path_strv, "PATH [...]" },
2926 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2927 { config_parse_exec_mount_flags, "MOUNTFLAG [...]" },
2928 { config_parse_unit_string_printf, "STRING" },
2929 { config_parse_trigger_unit, "UNIT" },
2930 { config_parse_timer, "TIMER" },
2931 { config_parse_path_spec, "PATH" },
2932 { config_parse_notify_access, "ACCESS" },
2933 { config_parse_ip_tos, "TOS" },
2934 { config_parse_unit_condition_path, "CONDITION" },
2935 { config_parse_unit_condition_string, "CONDITION" },
2936 { config_parse_unit_condition_null, "CONDITION" },
2937 { config_parse_unit_slice, "SLICE" },
2938 { config_parse_documentation, "URL" },
2939 { config_parse_service_timeout, "SECONDS" },
2940 { config_parse_start_limit_action, "ACTION" },
2941 { config_parse_set_status, "STATUS" },
2942 { config_parse_service_sockets, "SOCKETS" },
2943 { config_parse_environ, "ENVIRON" },
2944 #ifdef HAVE_SECCOMP
2945 { config_parse_syscall_filter, "SYSCALLS" },
2946 { config_parse_syscall_errno, "ERRNO" },
2947 #endif
2948 { config_parse_cpu_shares, "SHARES" },
2949 { config_parse_memory_limit, "LIMIT" },
2950 { config_parse_device_allow, "DEVICE" },
2951 { config_parse_device_policy, "POLICY" },
2952 { config_parse_blockio_bandwidth, "BANDWIDTH" },
2953 { config_parse_blockio_weight, "WEIGHT" },
2954 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
2955 { config_parse_long, "LONG" },
2956 { config_parse_socket_service, "SERVICE" },
2957 };
2958
2959 const char *prev = NULL;
2960 const char *i;
2961
2962 assert(f);
2963
2964 NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2965 const char *rvalue = "OTHER", *lvalue;
2966 unsigned j;
2967 size_t prefix_len;
2968 const char *dot;
2969 const ConfigPerfItem *p;
2970
2971 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2972
2973 dot = strchr(i, '.');
2974 lvalue = dot ? dot + 1 : i;
2975 prefix_len = dot-i;
2976
2977 if (dot)
2978 if (!prev || !strneq(prev, i, prefix_len+1)) {
2979 if (prev)
2980 fputc('\n', f);
2981
2982 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2983 }
2984
2985 for (j = 0; j < ELEMENTSOF(table); j++)
2986 if (p->parse == table[j].callback) {
2987 rvalue = table[j].rvalue;
2988 break;
2989 }
2990
2991 fprintf(f, "%s=%s\n", lvalue, rvalue);
2992 prev = i;
2993 }
2994 }