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