]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-unit-util.c
pid1: make TimeoutAbortSec settable for transient units
[thirdparty/systemd.git] / src / shared / bus-unit-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "bus-error.h"
5 #include "bus-unit-util.h"
6 #include "bus-util.h"
7 #include "cap-list.h"
8 #include "cgroup-setup.h"
9 #include "cgroup-util.h"
10 #include "condition.h"
11 #include "cpu-set-util.h"
12 #include "escape.h"
13 #include "exec-util.h"
14 #include "exit-status.h"
15 #include "hexdecoct.h"
16 #include "hostname-util.h"
17 #include "in-addr-util.h"
18 #include "ip-protocol-list.h"
19 #include "locale-util.h"
20 #include "log.h"
21 #include "missing_fs.h"
22 #include "mountpoint-util.h"
23 #include "nsflags.h"
24 #include "parse-util.h"
25 #include "process-util.h"
26 #include "rlimit-util.h"
27 #include "securebits-util.h"
28 #include "signal-util.h"
29 #include "socket-util.h"
30 #include "sort-util.h"
31 #include "string-util.h"
32 #include "syslog-util.h"
33 #include "terminal-util.h"
34 #include "unit-def.h"
35 #include "user-util.h"
36 #include "utf8.h"
37
38 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
39 assert(message);
40 assert(u);
41
42 u->machine = NULL;
43
44 return sd_bus_message_read(
45 message,
46 "(ssssssouso)",
47 &u->id,
48 &u->description,
49 &u->load_state,
50 &u->active_state,
51 &u->sub_state,
52 &u->following,
53 &u->unit_path,
54 &u->job_id,
55 &u->job_type,
56 &u->job_path);
57 }
58
59 #define DEFINE_BUS_APPEND_PARSE_PTR(bus_type, cast_type, type, parse_func) \
60 static int bus_append_##parse_func( \
61 sd_bus_message *m, \
62 const char *field, \
63 const char *eq) { \
64 type val; \
65 int r; \
66 \
67 r = parse_func(eq, &val); \
68 if (r < 0) \
69 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); \
70 \
71 r = sd_bus_message_append(m, "(sv)", field, \
72 bus_type, (cast_type) val); \
73 if (r < 0) \
74 return bus_log_create_error(r); \
75 \
76 return 1; \
77 }
78
79 #define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \
80 static int bus_append_##parse_func( \
81 sd_bus_message *m, \
82 const char *field, \
83 const char *eq) { \
84 int r; \
85 \
86 r = parse_func(eq); \
87 if (r < 0) \
88 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s: %s", field, eq); \
89 \
90 r = sd_bus_message_append(m, "(sv)", field, \
91 bus_type, (int32_t) r); \
92 if (r < 0) \
93 return bus_log_create_error(r); \
94 \
95 return 1; \
96 }
97
98 DEFINE_BUS_APPEND_PARSE("b", parse_boolean);
99 DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string);
100 DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string);
101 DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string);
102 DEFINE_BUS_APPEND_PARSE("i", log_level_from_string);
103 DEFINE_BUS_APPEND_PARSE("i", parse_errno);
104 DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string);
105 DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string);
106 DEFINE_BUS_APPEND_PARSE("i", signal_from_string);
107 DEFINE_BUS_APPEND_PARSE("i", parse_ip_protocol);
108 DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority);
109 DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice);
110 DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, safe_atoi);
111 DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, nsec_t, parse_nsec);
112 DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_blkio_weight_parse);
113 DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_shares_parse);
114 DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_weight_parse);
115 DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, unsigned long, mount_propagation_flags_from_string);
116 DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64);
117 DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode);
118 DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou);
119 DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64);
120
121 static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) {
122 int r;
123
124 r = sd_bus_message_append(m, "(sv)", field, "s", eq);
125 if (r < 0)
126 return bus_log_create_error(r);
127
128 return 1;
129 }
130
131 static int bus_append_strv(sd_bus_message *m, const char *field, const char *eq, ExtractFlags flags) {
132 const char *p;
133 int r;
134
135 r = sd_bus_message_open_container(m, 'r', "sv");
136 if (r < 0)
137 return bus_log_create_error(r);
138
139 r = sd_bus_message_append_basic(m, 's', field);
140 if (r < 0)
141 return bus_log_create_error(r);
142
143 r = sd_bus_message_open_container(m, 'v', "as");
144 if (r < 0)
145 return bus_log_create_error(r);
146
147 r = sd_bus_message_open_container(m, 'a', "s");
148 if (r < 0)
149 return bus_log_create_error(r);
150
151 for (p = eq;;) {
152 _cleanup_free_ char *word = NULL;
153
154 r = extract_first_word(&p, &word, NULL, flags);
155 if (r == 0)
156 break;
157 if (r == -ENOMEM)
158 return log_oom();
159 if (r < 0)
160 return log_error_errno(r, "Invalid syntax: %s", eq);
161
162 r = sd_bus_message_append_basic(m, 's', word);
163 if (r < 0)
164 return bus_log_create_error(r);
165 }
166
167 r = sd_bus_message_close_container(m);
168 if (r < 0)
169 return bus_log_create_error(r);
170
171 r = sd_bus_message_close_container(m);
172 if (r < 0)
173 return bus_log_create_error(r);
174
175 r = sd_bus_message_close_container(m);
176 if (r < 0)
177 return bus_log_create_error(r);
178
179 return 1;
180 }
181
182 static int bus_append_byte_array(sd_bus_message *m, const char *field, const void *buf, size_t n) {
183 int r;
184
185 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
186 if (r < 0)
187 return bus_log_create_error(r);
188
189 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
190 if (r < 0)
191 return bus_log_create_error(r);
192
193 r = sd_bus_message_open_container(m, 'v', "ay");
194 if (r < 0)
195 return bus_log_create_error(r);
196
197 r = sd_bus_message_append_array(m, 'y', buf, n);
198 if (r < 0)
199 return bus_log_create_error(r);
200
201 r = sd_bus_message_close_container(m);
202 if (r < 0)
203 return bus_log_create_error(r);
204
205 r = sd_bus_message_close_container(m);
206 if (r < 0)
207 return bus_log_create_error(r);
208
209 return 1;
210 }
211
212 static int bus_append_parse_sec_rename(sd_bus_message *m, const char *field, const char *eq) {
213 char *n;
214 usec_t t;
215 size_t l;
216 int r;
217
218 r = parse_sec(eq, &t);
219 if (r < 0)
220 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
221
222 l = strlen(field);
223 n = newa(char, l + 2);
224 /* Change suffix Sec → USec */
225 strcpy(mempcpy(n, field, l - 3), "USec");
226
227 r = sd_bus_message_append(m, "(sv)", n, "t", t);
228 if (r < 0)
229 return bus_log_create_error(r);
230
231 return 1;
232 }
233
234 static int bus_append_parse_size(sd_bus_message *m, const char *field, const char *eq, uint64_t base) {
235 uint64_t v;
236 int r;
237
238 r = parse_size(eq, base, &v);
239 if (r < 0)
240 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
241
242 r = sd_bus_message_append(m, "(sv)", field, "t", v);
243 if (r < 0)
244 return bus_log_create_error(r);
245
246 return 1;
247 }
248
249 static int bus_append_exec_command(sd_bus_message *m, const char *field, const char *eq) {
250 bool explicit_path = false, done = false;
251 _cleanup_strv_free_ char **l = NULL, **ex_opts = NULL;
252 _cleanup_free_ char *path = NULL, *upgraded_name = NULL;
253 ExecCommandFlags flags = 0;
254 bool is_ex_prop = endswith(field, "Ex");
255 int r;
256
257 do {
258 switch (*eq) {
259
260 case '-':
261 if (FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE))
262 done = true;
263 else {
264 flags |= EXEC_COMMAND_IGNORE_FAILURE;
265 eq++;
266 }
267 break;
268
269 case '@':
270 if (explicit_path)
271 done = true;
272 else {
273 explicit_path = true;
274 eq++;
275 }
276 break;
277
278 case ':':
279 if (FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND))
280 done = true;
281 else {
282 flags |= EXEC_COMMAND_NO_ENV_EXPAND;
283 eq++;
284 }
285 break;
286
287 case '+':
288 if (flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))
289 done = true;
290 else {
291 flags |= EXEC_COMMAND_FULLY_PRIVILEGED;
292 eq++;
293 }
294 break;
295
296 case '!':
297 if (flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC))
298 done = true;
299 else if (FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID)) {
300 flags &= ~EXEC_COMMAND_NO_SETUID;
301 flags |= EXEC_COMMAND_AMBIENT_MAGIC;
302 eq++;
303 } else {
304 flags |= EXEC_COMMAND_NO_SETUID;
305 eq++;
306 }
307 break;
308
309 default:
310 done = true;
311 break;
312 }
313 } while (!done);
314
315 if (!is_ex_prop && (flags & (EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))) {
316 /* Upgrade the ExecXYZ= property to ExecXYZEx= for convenience */
317 is_ex_prop = true;
318 upgraded_name = strjoin(field, "Ex");
319 if (!upgraded_name)
320 return log_oom();
321 }
322
323 if (is_ex_prop) {
324 r = exec_command_flags_to_strv(flags, &ex_opts);
325 if (r < 0)
326 return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m");
327 }
328
329 if (explicit_path) {
330 r = extract_first_word(&eq, &path, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
331 if (r < 0)
332 return log_error_errno(r, "Failed to parse path: %m");
333 }
334
335 r = strv_split_extract(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
336 if (r < 0)
337 return log_error_errno(r, "Failed to parse command line: %m");
338
339 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
340 if (r < 0)
341 return bus_log_create_error(r);
342
343 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, upgraded_name ?: field);
344 if (r < 0)
345 return bus_log_create_error(r);
346
347 r = sd_bus_message_open_container(m, 'v', is_ex_prop ? "a(sasas)" : "a(sasb)");
348 if (r < 0)
349 return bus_log_create_error(r);
350
351 r = sd_bus_message_open_container(m, 'a', is_ex_prop ? "(sasas)" : "(sasb)");
352 if (r < 0)
353 return bus_log_create_error(r);
354
355 if (!strv_isempty(l)) {
356
357 r = sd_bus_message_open_container(m, 'r', is_ex_prop ? "sasas" : "sasb");
358 if (r < 0)
359 return bus_log_create_error(r);
360
361 r = sd_bus_message_append(m, "s", path ?: l[0]);
362 if (r < 0)
363 return bus_log_create_error(r);
364
365 r = sd_bus_message_append_strv(m, l);
366 if (r < 0)
367 return bus_log_create_error(r);
368
369 r = is_ex_prop ? sd_bus_message_append_strv(m, ex_opts) : sd_bus_message_append(m, "b", FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE));
370 if (r < 0)
371 return bus_log_create_error(r);
372
373 r = sd_bus_message_close_container(m);
374 if (r < 0)
375 return bus_log_create_error(r);
376 }
377
378 r = sd_bus_message_close_container(m);
379 if (r < 0)
380 return bus_log_create_error(r);
381
382 r = sd_bus_message_close_container(m);
383 if (r < 0)
384 return bus_log_create_error(r);
385
386 r = sd_bus_message_close_container(m);
387 if (r < 0)
388 return bus_log_create_error(r);
389
390 return 1;
391 }
392
393 static int bus_append_ip_address_access(sd_bus_message *m, int family, const union in_addr_union *prefix, unsigned char prefixlen) {
394 int r;
395
396 assert(m);
397 assert(prefix);
398
399 r = sd_bus_message_open_container(m, 'r', "iayu");
400 if (r < 0)
401 return r;
402
403 r = sd_bus_message_append(m, "i", family);
404 if (r < 0)
405 return r;
406
407 r = sd_bus_message_append_array(m, 'y', prefix, FAMILY_ADDRESS_SIZE(family));
408 if (r < 0)
409 return r;
410
411 r = sd_bus_message_append(m, "u", prefixlen);
412 if (r < 0)
413 return r;
414
415 return sd_bus_message_close_container(m);
416 }
417
418 static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) {
419 int r;
420
421 if (STR_IN_SET(field, "DevicePolicy", "Slice"))
422 return bus_append_string(m, field, eq);
423
424 if (STR_IN_SET(field, "CPUAccounting",
425 "MemoryAccounting",
426 "IOAccounting",
427 "BlockIOAccounting",
428 "TasksAccounting",
429 "IPAccounting"))
430 return bus_append_parse_boolean(m, field, eq);
431
432 if (STR_IN_SET(field, "CPUWeight",
433 "StartupCPUWeight",
434 "IOWeight",
435 "StartupIOWeight"))
436 return bus_append_cg_weight_parse(m, field, eq);
437
438 if (STR_IN_SET(field, "CPUShares",
439 "StartupCPUShares"))
440 return bus_append_cg_cpu_shares_parse(m, field, eq);
441
442 if (STR_IN_SET(field, "AllowedCPUs",
443 "AllowedMemoryNodes")) {
444 _cleanup_(cpu_set_reset) CPUSet cpuset = {};
445 _cleanup_free_ uint8_t *array = NULL;
446 size_t allocated;
447
448 r = parse_cpu_set(eq, &cpuset);
449 if (r < 0)
450 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
451
452 r = cpu_set_to_dbus(&cpuset, &array, &allocated);
453 if (r < 0)
454 return log_error_errno(r, "Failed to serialize CPUSet: %m");
455
456 return bus_append_byte_array(m, field, array, allocated);
457 }
458
459 if (STR_IN_SET(field, "BlockIOWeight",
460 "StartupBlockIOWeight"))
461 return bus_append_cg_blkio_weight_parse(m, field, eq);
462
463 if (streq(field, "DisableControllers"))
464 return bus_append_strv(m, "DisableControllers", eq, EXTRACT_UNQUOTE);
465
466 if (streq(field, "Delegate")) {
467 r = parse_boolean(eq);
468 if (r < 0)
469 return bus_append_strv(m, "DelegateControllers", eq, EXTRACT_UNQUOTE);
470
471 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", r);
472 if (r < 0)
473 return bus_log_create_error(r);
474
475 return 1;
476 }
477
478 if (STR_IN_SET(field, "MemoryMin",
479 "DefaultMemoryLow",
480 "DefaultMemoryMin",
481 "MemoryLow",
482 "MemoryHigh",
483 "MemoryMax",
484 "MemorySwapMax",
485 "MemoryLimit",
486 "TasksMax")) {
487
488 if (isempty(eq) || streq(eq, "infinity")) {
489 r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX);
490 if (r < 0)
491 return bus_log_create_error(r);
492 return 1;
493 }
494
495 r = parse_permille(eq);
496 if (r >= 0) {
497 char *n;
498
499 /* When this is a percentage we'll convert this into a relative value in the range 0…UINT32_MAX
500 * and pass it in the MemoryLowScale property (and related ones). This way the physical memory
501 * size can be determined server-side. */
502
503 n = strjoina(field, "Scale");
504 r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U));
505 if (r < 0)
506 return bus_log_create_error(r);
507
508 return 1;
509 }
510
511 if (streq(field, "TasksMax"))
512 return bus_append_safe_atou64(m, field, eq);
513
514 return bus_append_parse_size(m, field, eq, 1024);
515 }
516
517 if (streq(field, "CPUQuota")) {
518 if (isempty(eq))
519 r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
520 else {
521 r = parse_permille_unbounded(eq);
522 if (r == 0)
523 return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
524 "CPU quota too small.");
525 if (r < 0)
526 return log_error_errno(r, "CPU quota '%s' invalid.", eq);
527
528 r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", (((uint64_t) r * USEC_PER_SEC) / 1000U));
529 }
530
531 if (r < 0)
532 return bus_log_create_error(r);
533
534 return 1;
535 }
536
537 if (streq(field, "CPUQuotaPeriodSec")) {
538 usec_t u = USEC_INFINITY;
539
540 r = parse_sec_def_infinity(eq, &u);
541 if (r < 0)
542 return log_error_errno(r, "CPU quota period '%s' invalid.", eq);
543
544 r = sd_bus_message_append(m, "(sv)", "CPUQuotaPeriodUSec", "t", u);
545 if (r < 0)
546 return bus_log_create_error(r);
547
548 return 1;
549 }
550
551 if (streq(field, "DeviceAllow")) {
552 if (isempty(eq))
553 r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0);
554 else {
555 const char *path = eq, *rwm = NULL, *e;
556
557 e = strchr(eq, ' ');
558 if (e) {
559 path = strndupa(eq, e - eq);
560 rwm = e+1;
561 }
562
563 r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, path, strempty(rwm));
564 }
565
566 if (r < 0)
567 return bus_log_create_error(r);
568
569 return 1;
570 }
571
572 if (cgroup_io_limit_type_from_string(field) >= 0 || STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
573 if (isempty(eq))
574 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0);
575 else {
576 const char *path, *bandwidth, *e;
577 uint64_t bytes;
578
579 e = strchr(eq, ' ');
580 if (!e)
581 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
582 "Failed to parse %s value %s.",
583 field, eq);
584
585 path = strndupa(eq, e - eq);
586 bandwidth = e+1;
587
588 if (streq(bandwidth, "infinity"))
589 bytes = CGROUP_LIMIT_MAX;
590 else {
591 r = parse_size(bandwidth, 1000, &bytes);
592 if (r < 0)
593 return log_error_errno(r, "Failed to parse byte value %s: %m", bandwidth);
594 }
595
596 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, bytes);
597 }
598
599 if (r < 0)
600 return bus_log_create_error(r);
601
602 return 1;
603 }
604
605 if (STR_IN_SET(field, "IODeviceWeight",
606 "BlockIODeviceWeight")) {
607 if (isempty(eq))
608 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0);
609 else {
610 const char *path, *weight, *e;
611 uint64_t u;
612
613 e = strchr(eq, ' ');
614 if (!e)
615 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
616 "Failed to parse %s value %s.",
617 field, eq);
618
619 path = strndupa(eq, e - eq);
620 weight = e+1;
621
622 r = safe_atou64(weight, &u);
623 if (r < 0)
624 return log_error_errno(r, "Failed to parse %s value %s: %m", field, weight);
625
626 r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, u);
627 }
628
629 if (r < 0)
630 return bus_log_create_error(r);
631
632 return 1;
633 }
634
635 if (streq(field, "IODeviceLatencyTargetSec")) {
636 const char *field_usec = "IODeviceLatencyTargetUSec";
637
638 if (isempty(eq))
639 r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", USEC_INFINITY);
640 else {
641 const char *path, *target, *e;
642 usec_t usec;
643
644 e = strchr(eq, ' ');
645 if (!e)
646 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
647 "Failed to parse %s value %s.",
648 field, eq);
649
650 path = strndupa(eq, e - eq);
651 target = e+1;
652
653 r = parse_sec(target, &usec);
654 if (r < 0)
655 return log_error_errno(r, "Failed to parse %s value %s: %m", field, target);
656
657 r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", 1, path, usec);
658 }
659
660 if (r < 0)
661 return bus_log_create_error(r);
662
663 return 1;
664 }
665
666 if (STR_IN_SET(field, "IPAddressAllow",
667 "IPAddressDeny")) {
668 unsigned char prefixlen;
669 union in_addr_union prefix = {};
670 int family;
671
672 if (isempty(eq)) {
673 r = sd_bus_message_append(m, "(sv)", field, "a(iayu)", 0);
674 if (r < 0)
675 return bus_log_create_error(r);
676
677 return 1;
678 }
679
680 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
681 if (r < 0)
682 return bus_log_create_error(r);
683
684 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
685 if (r < 0)
686 return bus_log_create_error(r);
687
688 r = sd_bus_message_open_container(m, 'v', "a(iayu)");
689 if (r < 0)
690 return bus_log_create_error(r);
691
692 r = sd_bus_message_open_container(m, 'a', "(iayu)");
693 if (r < 0)
694 return bus_log_create_error(r);
695
696 if (streq(eq, "any")) {
697 /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
698
699 r = bus_append_ip_address_access(m, AF_INET, &prefix, 0);
700 if (r < 0)
701 return bus_log_create_error(r);
702
703 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 0);
704 if (r < 0)
705 return bus_log_create_error(r);
706
707 } else if (is_localhost(eq)) {
708 /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
709
710 prefix.in.s_addr = htobe32(0x7f000000);
711 r = bus_append_ip_address_access(m, AF_INET, &prefix, 8);
712 if (r < 0)
713 return bus_log_create_error(r);
714
715 prefix.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
716 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 128);
717 if (r < 0)
718 return r;
719
720 } else if (streq(eq, "link-local")) {
721 /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
722
723 prefix.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
724 r = bus_append_ip_address_access(m, AF_INET, &prefix, 16);
725 if (r < 0)
726 return bus_log_create_error(r);
727
728 prefix.in6 = (struct in6_addr) {
729 .s6_addr32[0] = htobe32(0xfe800000)
730 };
731 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 64);
732 if (r < 0)
733 return bus_log_create_error(r);
734
735 } else if (streq(eq, "multicast")) {
736 /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
737
738 prefix.in.s_addr = htobe32((UINT32_C(224) << 24));
739 r = bus_append_ip_address_access(m, AF_INET, &prefix, 4);
740 if (r < 0)
741 return bus_log_create_error(r);
742
743 prefix.in6 = (struct in6_addr) {
744 .s6_addr32[0] = htobe32(0xff000000)
745 };
746 r = bus_append_ip_address_access(m, AF_INET6, &prefix, 8);
747 if (r < 0)
748 return bus_log_create_error(r);
749
750 } else {
751 for (;;) {
752 _cleanup_free_ char *word = NULL;
753
754 r = extract_first_word(&eq, &word, NULL, 0);
755 if (r == 0)
756 break;
757 if (r == -ENOMEM)
758 return log_oom();
759 if (r < 0)
760 return log_error_errno(r, "Failed to parse %s: %s", field, eq);
761
762 r = in_addr_prefix_from_string_auto(word, &family, &prefix, &prefixlen);
763 if (r < 0)
764 return log_error_errno(r, "Failed to parse IP address prefix: %s", word);
765
766 r = bus_append_ip_address_access(m, family, &prefix, prefixlen);
767 if (r < 0)
768 return bus_log_create_error(r);
769 }
770 }
771
772 r = sd_bus_message_close_container(m);
773 if (r < 0)
774 return bus_log_create_error(r);
775
776 r = sd_bus_message_close_container(m);
777 if (r < 0)
778 return bus_log_create_error(r);
779
780 r = sd_bus_message_close_container(m);
781 if (r < 0)
782 return bus_log_create_error(r);
783
784 return 1;
785 }
786
787 if (STR_IN_SET(field, "IPIngressFilterPath",
788 "IPEgressFilterPath")) {
789 if (isempty(eq))
790 r = sd_bus_message_append(m, "(sv)", field, "as", 0);
791 else
792 r = sd_bus_message_append(m, "(sv)", field, "as", 1, eq);
793
794 if (r < 0)
795 return bus_log_create_error(r);
796
797 return 1;
798 }
799
800 return 0;
801 }
802
803 static int bus_append_automount_property(sd_bus_message *m, const char *field, const char *eq) {
804 if (streq(field, "Where"))
805 return bus_append_string(m, field, eq);
806
807 if (streq(field, "DirectoryMode"))
808 return bus_append_parse_mode(m, field, eq);
809
810 if (streq(field, "TimeoutIdleSec"))
811 return bus_append_parse_sec_rename(m, field, eq);
812
813 return 0;
814 }
815
816 static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) {
817 const char *suffix;
818 int r;
819
820 if (STR_IN_SET(field, "User",
821 "Group",
822 "UtmpIdentifier",
823 "UtmpMode",
824 "PAMName",
825 "TTYPath",
826 "WorkingDirectory",
827 "RootDirectory",
828 "SyslogIdentifier",
829 "ProtectSystem",
830 "ProtectHome",
831 "SELinuxContext",
832 "RootImage",
833 "RuntimeDirectoryPreserve",
834 "Personality",
835 "KeyringMode",
836 "NetworkNamespacePath"))
837 return bus_append_string(m, field, eq);
838
839 if (STR_IN_SET(field, "IgnoreSIGPIPE",
840 "TTYVHangup",
841 "TTYReset",
842 "TTYVTDisallocate",
843 "PrivateTmp",
844 "PrivateDevices",
845 "PrivateNetwork",
846 "PrivateUsers",
847 "PrivateMounts",
848 "NoNewPrivileges",
849 "SyslogLevelPrefix",
850 "MemoryDenyWriteExecute",
851 "RestrictRealtime",
852 "DynamicUser",
853 "RemoveIPC",
854 "ProtectKernelTunables",
855 "ProtectKernelModules",
856 "ProtectKernelLogs",
857 "ProtectControlGroups",
858 "MountAPIVFS",
859 "CPUSchedulingResetOnFork",
860 "LockPersonality",
861 "ProtectHostname",
862 "RestrictSUIDSGID"))
863 return bus_append_parse_boolean(m, field, eq);
864
865 if (STR_IN_SET(field, "ReadWriteDirectories",
866 "ReadOnlyDirectories",
867 "InaccessibleDirectories",
868 "ReadWritePaths",
869 "ReadOnlyPaths",
870 "InaccessiblePaths",
871 "RuntimeDirectory",
872 "StateDirectory",
873 "CacheDirectory",
874 "LogsDirectory",
875 "ConfigurationDirectory",
876 "SupplementaryGroups",
877 "SystemCallArchitectures"))
878 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
879
880 if (STR_IN_SET(field, "SyslogLevel",
881 "LogLevelMax"))
882 return bus_append_log_level_from_string(m, field, eq);
883
884 if (streq(field, "SyslogFacility"))
885 return bus_append_log_facility_unshifted_from_string(m, field, eq);
886
887 if (streq(field, "SecureBits"))
888 return bus_append_secure_bits_from_string(m, field, eq);
889
890 if (streq(field, "CPUSchedulingPolicy"))
891 return bus_append_sched_policy_from_string(m, field, eq);
892
893 if (STR_IN_SET(field, "CPUSchedulingPriority",
894 "OOMScoreAdjust"))
895 return bus_append_safe_atoi(m, field, eq);
896
897 if (streq(field, "Nice"))
898 return bus_append_parse_nice(m, field, eq);
899
900 if (streq(field, "SystemCallErrorNumber"))
901 return bus_append_parse_errno(m, field, eq);
902
903 if (streq(field, "IOSchedulingClass"))
904 return bus_append_ioprio_class_from_string(m, field, eq);
905
906 if (streq(field, "IOSchedulingPriority"))
907 return bus_append_ioprio_parse_priority(m, field, eq);
908
909 if (STR_IN_SET(field, "RuntimeDirectoryMode",
910 "StateDirectoryMode",
911 "CacheDirectoryMode",
912 "LogsDirectoryMode",
913 "ConfigurationDirectoryMode",
914 "UMask"))
915 return bus_append_parse_mode(m, field, eq);
916
917 if (streq(field, "TimerSlackNSec"))
918 return bus_append_parse_nsec(m, field, eq);
919
920 if (streq(field, "LogRateLimitIntervalSec"))
921 return bus_append_parse_sec_rename(m, field, eq);
922
923 if (streq(field, "LogRateLimitBurst"))
924 return bus_append_safe_atou(m, field, eq);
925
926 if (streq(field, "MountFlags"))
927 return bus_append_mount_propagation_flags_from_string(m, field, eq);
928
929 if (STR_IN_SET(field, "Environment",
930 "UnsetEnvironment",
931 "PassEnvironment"))
932 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
933
934 if (streq(field, "EnvironmentFile")) {
935 if (isempty(eq))
936 r = sd_bus_message_append(m, "(sv)", "EnvironmentFiles", "a(sb)", 0);
937 else
938 r = sd_bus_message_append(m, "(sv)", "EnvironmentFiles", "a(sb)", 1,
939 eq[0] == '-' ? eq + 1 : eq,
940 eq[0] == '-');
941 if (r < 0)
942 return bus_log_create_error(r);
943
944 return 1;
945 }
946
947 if (streq(field, "LogExtraFields")) {
948 r = sd_bus_message_open_container(m, 'r', "sv");
949 if (r < 0)
950 return bus_log_create_error(r);
951
952 r = sd_bus_message_append_basic(m, 's', "LogExtraFields");
953 if (r < 0)
954 return bus_log_create_error(r);
955
956 r = sd_bus_message_open_container(m, 'v', "aay");
957 if (r < 0)
958 return bus_log_create_error(r);
959
960 r = sd_bus_message_open_container(m, 'a', "ay");
961 if (r < 0)
962 return bus_log_create_error(r);
963
964 r = sd_bus_message_append_array(m, 'y', eq, strlen(eq));
965 if (r < 0)
966 return bus_log_create_error(r);
967
968 r = sd_bus_message_close_container(m);
969 if (r < 0)
970 return bus_log_create_error(r);
971
972 r = sd_bus_message_close_container(m);
973 if (r < 0)
974 return bus_log_create_error(r);
975
976 r = sd_bus_message_close_container(m);
977 if (r < 0)
978 return bus_log_create_error(r);
979
980 return 1;
981 }
982
983 if (STR_IN_SET(field, "StandardInput",
984 "StandardOutput",
985 "StandardError")) {
986 const char *n, *appended;
987
988 if ((n = startswith(eq, "fd:"))) {
989 appended = strjoina(field, "FileDescriptorName");
990 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
991 } else if ((n = startswith(eq, "file:"))) {
992 appended = strjoina(field, "File");
993 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
994 } else if ((n = startswith(eq, "append:"))) {
995 appended = strjoina(field, "FileToAppend");
996 r = sd_bus_message_append(m, "(sv)", appended, "s", n);
997 } else
998 r = sd_bus_message_append(m, "(sv)", field, "s", eq);
999 if (r < 0)
1000 return bus_log_create_error(r);
1001
1002 return 1;
1003 }
1004
1005 if (streq(field, "StandardInputText")) {
1006 _cleanup_free_ char *unescaped = NULL;
1007
1008 r = cunescape(eq, 0, &unescaped);
1009 if (r < 0)
1010 return log_error_errno(r, "Failed to unescape text '%s': %m", eq);
1011
1012 if (!strextend(&unescaped, "\n", NULL))
1013 return log_oom();
1014
1015 /* Note that we don't expand specifiers here, but that should be OK, as this is a programmatic
1016 * interface anyway */
1017
1018 return bus_append_byte_array(m, field, unescaped, strlen(unescaped));
1019 }
1020
1021 if (streq(field, "StandardInputData")) {
1022 _cleanup_free_ void *decoded = NULL;
1023 size_t sz;
1024
1025 r = unbase64mem(eq, (size_t) -1, &decoded, &sz);
1026 if (r < 0)
1027 return log_error_errno(r, "Failed to decode base64 data '%s': %m", eq);
1028
1029 return bus_append_byte_array(m, field, decoded, sz);
1030 }
1031
1032 if ((suffix = startswith(field, "Limit"))) {
1033 int rl;
1034
1035 rl = rlimit_from_string(suffix);
1036 if (rl >= 0) {
1037 const char *sn;
1038 struct rlimit l;
1039
1040 r = rlimit_parse(rl, eq, &l);
1041 if (r < 0)
1042 return log_error_errno(r, "Failed to parse resource limit: %s", eq);
1043
1044 r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
1045 if (r < 0)
1046 return bus_log_create_error(r);
1047
1048 sn = strjoina(field, "Soft");
1049 r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
1050 if (r < 0)
1051 return bus_log_create_error(r);
1052
1053 return 1;
1054 }
1055 }
1056
1057 if (STR_IN_SET(field, "AppArmorProfile",
1058 "SmackProcessLabel")) {
1059 int ignore = 0;
1060 const char *s = eq;
1061
1062 if (eq[0] == '-') {
1063 ignore = 1;
1064 s = eq + 1;
1065 }
1066
1067 r = sd_bus_message_append(m, "(sv)", field, "(bs)", ignore, s);
1068 if (r < 0)
1069 return bus_log_create_error(r);
1070
1071 return 1;
1072 }
1073
1074 if (STR_IN_SET(field, "CapabilityBoundingSet",
1075 "AmbientCapabilities")) {
1076 uint64_t sum = 0;
1077 bool invert = false;
1078 const char *p = eq;
1079
1080 if (*p == '~') {
1081 invert = true;
1082 p++;
1083 }
1084
1085 r = capability_set_from_string(p, &sum);
1086 if (r < 0)
1087 return log_error_errno(r, "Failed to parse %s value %s: %m", field, eq);
1088
1089 sum = invert ? ~sum : sum;
1090
1091 r = sd_bus_message_append(m, "(sv)", field, "t", sum);
1092 if (r < 0)
1093 return bus_log_create_error(r);
1094
1095 return 1;
1096 }
1097
1098 if (streq(field, "CPUAffinity")) {
1099 _cleanup_(cpu_set_reset) CPUSet cpuset = {};
1100 _cleanup_free_ uint8_t *array = NULL;
1101 size_t allocated;
1102
1103 r = parse_cpu_set(eq, &cpuset);
1104 if (r < 0)
1105 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
1106
1107 r = cpu_set_to_dbus(&cpuset, &array, &allocated);
1108 if (r < 0)
1109 return log_error_errno(r, "Failed to serialize CPUAffinity: %m");
1110
1111 return bus_append_byte_array(m, field, array, allocated);
1112 }
1113
1114 if (streq(field, "NUMAPolicy")) {
1115 r = mpol_from_string(eq);
1116 if (r < 0)
1117 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
1118
1119 r = sd_bus_message_append(m, "(sv)", field, "i", (int32_t) r);
1120 if (r < 0)
1121 return bus_log_create_error(r);
1122
1123 return 1;
1124 }
1125
1126 if (streq(field, "NUMAMask")) {
1127 _cleanup_(cpu_set_reset) CPUSet nodes = {};
1128 _cleanup_free_ uint8_t *array = NULL;
1129 size_t allocated;
1130
1131 r = parse_cpu_set(eq, &nodes);
1132 if (r < 0)
1133 return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
1134
1135 r = cpu_set_to_dbus(&nodes, &array, &allocated);
1136 if (r < 0)
1137 return log_error_errno(r, "Failed to serialize NUMAMask: %m");
1138
1139 return bus_append_byte_array(m, field, array, allocated);
1140 }
1141
1142 if (STR_IN_SET(field, "RestrictAddressFamilies",
1143 "SystemCallFilter")) {
1144 int whitelist = 1;
1145 const char *p = eq;
1146
1147 if (*p == '~') {
1148 whitelist = 0;
1149 p++;
1150 }
1151
1152 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1153 if (r < 0)
1154 return bus_log_create_error(r);
1155
1156 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1157 if (r < 0)
1158 return bus_log_create_error(r);
1159
1160 r = sd_bus_message_open_container(m, 'v', "(bas)");
1161 if (r < 0)
1162 return bus_log_create_error(r);
1163
1164 r = sd_bus_message_open_container(m, 'r', "bas");
1165 if (r < 0)
1166 return bus_log_create_error(r);
1167
1168 r = sd_bus_message_append_basic(m, 'b', &whitelist);
1169 if (r < 0)
1170 return bus_log_create_error(r);
1171
1172 r = sd_bus_message_open_container(m, 'a', "s");
1173 if (r < 0)
1174 return bus_log_create_error(r);
1175
1176 for (;;) {
1177 _cleanup_free_ char *word = NULL;
1178
1179 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
1180 if (r == 0)
1181 break;
1182 if (r == -ENOMEM)
1183 return log_oom();
1184 if (r < 0)
1185 return log_error_errno(r, "Invalid syntax: %s", eq);
1186
1187 r = sd_bus_message_append_basic(m, 's', word);
1188 if (r < 0)
1189 return bus_log_create_error(r);
1190 }
1191
1192 r = sd_bus_message_close_container(m);
1193 if (r < 0)
1194 return bus_log_create_error(r);
1195
1196 r = sd_bus_message_close_container(m);
1197 if (r < 0)
1198 return bus_log_create_error(r);
1199
1200 r = sd_bus_message_close_container(m);
1201 if (r < 0)
1202 return bus_log_create_error(r);
1203
1204 r = sd_bus_message_close_container(m);
1205 if (r < 0)
1206 return bus_log_create_error(r);
1207
1208 return 1;
1209 }
1210
1211 if (streq(field, "RestrictNamespaces")) {
1212 bool invert = false;
1213 unsigned long flags;
1214
1215 r = parse_boolean(eq);
1216 if (r > 0)
1217 flags = 0;
1218 else if (r == 0)
1219 flags = NAMESPACE_FLAGS_ALL;
1220 else {
1221 if (eq[0] == '~') {
1222 invert = true;
1223 eq++;
1224 }
1225
1226 r = namespace_flags_from_string(eq, &flags);
1227 if (r < 0)
1228 return log_error_errno(r, "Failed to parse %s value %s.", field, eq);
1229 }
1230
1231 if (invert)
1232 flags = (~flags) & NAMESPACE_FLAGS_ALL;
1233
1234 r = sd_bus_message_append(m, "(sv)", field, "t", (uint64_t) flags);
1235 if (r < 0)
1236 return bus_log_create_error(r);
1237
1238 return 1;
1239 }
1240
1241 if (STR_IN_SET(field, "BindPaths",
1242 "BindReadOnlyPaths")) {
1243 const char *p = eq;
1244
1245 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1246 if (r < 0)
1247 return bus_log_create_error(r);
1248
1249 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1250 if (r < 0)
1251 return bus_log_create_error(r);
1252
1253 r = sd_bus_message_open_container(m, 'v', "a(ssbt)");
1254 if (r < 0)
1255 return bus_log_create_error(r);
1256
1257 r = sd_bus_message_open_container(m, 'a', "(ssbt)");
1258 if (r < 0)
1259 return bus_log_create_error(r);
1260
1261 for (;;) {
1262 _cleanup_free_ char *source = NULL, *destination = NULL;
1263 char *s = NULL, *d = NULL;
1264 bool ignore_enoent = false;
1265 uint64_t flags = MS_REC;
1266
1267 r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
1268 if (r < 0)
1269 return log_error_errno(r, "Failed to parse argument: %m");
1270 if (r == 0)
1271 break;
1272
1273 s = source;
1274 if (s[0] == '-') {
1275 ignore_enoent = true;
1276 s++;
1277 }
1278
1279 if (p && p[-1] == ':') {
1280 r = extract_first_word(&p, &destination, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
1281 if (r < 0)
1282 return log_error_errno(r, "Failed to parse argument: %m");
1283 if (r == 0)
1284 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1285 "Missing argument after ':': %s",
1286 eq);
1287
1288 d = destination;
1289
1290 if (p && p[-1] == ':') {
1291 _cleanup_free_ char *options = NULL;
1292
1293 r = extract_first_word(&p, &options, NULL, EXTRACT_UNQUOTE);
1294 if (r < 0)
1295 return log_error_errno(r, "Failed to parse argument: %m");
1296
1297 if (isempty(options) || streq(options, "rbind"))
1298 flags = MS_REC;
1299 else if (streq(options, "norbind"))
1300 flags = 0;
1301 else
1302 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1303 "Unknown options: %s",
1304 eq);
1305 }
1306 } else
1307 d = s;
1308
1309 r = sd_bus_message_append(m, "(ssbt)", s, d, ignore_enoent, flags);
1310 if (r < 0)
1311 return bus_log_create_error(r);
1312 }
1313
1314 r = sd_bus_message_close_container(m);
1315 if (r < 0)
1316 return bus_log_create_error(r);
1317
1318 r = sd_bus_message_close_container(m);
1319 if (r < 0)
1320 return bus_log_create_error(r);
1321
1322 r = sd_bus_message_close_container(m);
1323 if (r < 0)
1324 return bus_log_create_error(r);
1325
1326 return 1;
1327 }
1328
1329 if (streq(field, "TemporaryFileSystem")) {
1330 const char *p = eq;
1331
1332 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1333 if (r < 0)
1334 return bus_log_create_error(r);
1335
1336 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1337 if (r < 0)
1338 return bus_log_create_error(r);
1339
1340 r = sd_bus_message_open_container(m, 'v', "a(ss)");
1341 if (r < 0)
1342 return bus_log_create_error(r);
1343
1344 r = sd_bus_message_open_container(m, 'a', "(ss)");
1345 if (r < 0)
1346 return bus_log_create_error(r);
1347
1348 for (;;) {
1349 _cleanup_free_ char *word = NULL, *path = NULL;
1350 const char *w;
1351
1352 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
1353 if (r < 0)
1354 return log_error_errno(r, "Failed to parse argument: %m");
1355 if (r == 0)
1356 break;
1357
1358 w = word;
1359 r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
1360 if (r < 0)
1361 return log_error_errno(r, "Failed to parse argument: %m");
1362 if (r == 0)
1363 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1364 "Failed to parse argument: %s",
1365 p);
1366
1367 r = sd_bus_message_append(m, "(ss)", path, w);
1368 if (r < 0)
1369 return bus_log_create_error(r);
1370 }
1371
1372 r = sd_bus_message_close_container(m);
1373 if (r < 0)
1374 return bus_log_create_error(r);
1375
1376 r = sd_bus_message_close_container(m);
1377 if (r < 0)
1378 return bus_log_create_error(r);
1379
1380 r = sd_bus_message_close_container(m);
1381 if (r < 0)
1382 return bus_log_create_error(r);
1383
1384 return 1;
1385 }
1386
1387 return 0;
1388 }
1389
1390 static int bus_append_kill_property(sd_bus_message *m, const char *field, const char *eq) {
1391 if (streq(field, "KillMode"))
1392 return bus_append_string(m, field, eq);
1393
1394 if (STR_IN_SET(field, "SendSIGHUP",
1395 "SendSIGKILL"))
1396 return bus_append_parse_boolean(m, field, eq);
1397
1398 if (STR_IN_SET(field, "KillSignal",
1399 "RestartKillSignal",
1400 "FinalKillSignal",
1401 "WatchdogSignal"))
1402 return bus_append_signal_from_string(m, field, eq);
1403
1404 return 0;
1405 }
1406
1407 static int bus_append_mount_property(sd_bus_message *m, const char *field, const char *eq) {
1408
1409 if (STR_IN_SET(field, "What",
1410 "Where",
1411 "Options",
1412 "Type"))
1413 return bus_append_string(m, field, eq);
1414
1415 if (streq(field, "TimeoutSec"))
1416 return bus_append_parse_sec_rename(m, field, eq);
1417
1418 if (streq(field, "DirectoryMode"))
1419 return bus_append_parse_mode(m, field, eq);
1420
1421 if (STR_IN_SET(field, "SloppyOptions",
1422 "LazyUnmount",
1423 "ForceUnmount"))
1424 return bus_append_parse_boolean(m, field, eq);
1425
1426 return 0;
1427 }
1428
1429 static int bus_append_path_property(sd_bus_message *m, const char *field, const char *eq) {
1430 int r;
1431
1432 if (streq(field, "MakeDirectory"))
1433 return bus_append_parse_boolean(m, field, eq);
1434
1435 if (streq(field, "DirectoryMode"))
1436 return bus_append_parse_mode(m, field, eq);
1437
1438 if (STR_IN_SET(field, "PathExists",
1439 "PathExistsGlob",
1440 "PathChanged",
1441 "PathModified",
1442 "DirectoryNotEmpty")) {
1443 if (isempty(eq))
1444 r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 0);
1445 else
1446 r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 1, field, eq);
1447 if (r < 0)
1448 return bus_log_create_error(r);
1449
1450 return 1;
1451 }
1452
1453 return 0;
1454 }
1455
1456 static int bus_append_scope_property(sd_bus_message *m, const char *field, const char *eq) {
1457 if (streq(field, "RuntimeMaxSec"))
1458 return bus_append_parse_sec_rename(m, field, eq);
1459
1460 if (streq(field, "TimeoutStopSec"))
1461 return bus_append_parse_sec_rename(m, field, eq);
1462
1463 return 0;
1464 }
1465
1466 static int bus_append_service_property(sd_bus_message *m, const char *field, const char *eq) {
1467 int r;
1468
1469 if (STR_IN_SET(field, "PIDFile",
1470 "Type",
1471 "Restart",
1472 "BusName",
1473 "NotifyAccess",
1474 "USBFunctionDescriptors",
1475 "USBFunctionStrings",
1476 "OOMPolicy"))
1477 return bus_append_string(m, field, eq);
1478
1479 if (STR_IN_SET(field, "PermissionsStartOnly",
1480 "RootDirectoryStartOnly",
1481 "RemainAfterExit",
1482 "GuessMainPID"))
1483 return bus_append_parse_boolean(m, field, eq);
1484
1485 if (STR_IN_SET(field, "RestartSec",
1486 "TimeoutStartSec",
1487 "TimeoutStopSec",
1488 "TimeoutAbortSec",
1489 "RuntimeMaxSec",
1490 "WatchdogSec"))
1491 return bus_append_parse_sec_rename(m, field, eq);
1492
1493 if (streq(field, "TimeoutSec")) {
1494 r = bus_append_parse_sec_rename(m, "TimeoutStartSec", eq);
1495 if (r < 0)
1496 return r;
1497
1498 return bus_append_parse_sec_rename(m, "TimeoutStopSec", eq);
1499 }
1500
1501 if (streq(field, "FileDescriptorStoreMax"))
1502 return bus_append_safe_atou(m, field, eq);
1503
1504 if (STR_IN_SET(field, "ExecCondition",
1505 "ExecStartPre",
1506 "ExecStart",
1507 "ExecStartPost",
1508 "ExecConditionEx",
1509 "ExecStartPreEx",
1510 "ExecStartEx",
1511 "ExecStartPostEx",
1512 "ExecReload",
1513 "ExecStop",
1514 "ExecStopPost",
1515 "ExecReloadEx",
1516 "ExecStopEx",
1517 "ExecStopPostEx"))
1518 return bus_append_exec_command(m, field, eq);
1519
1520 if (STR_IN_SET(field, "RestartPreventExitStatus",
1521 "RestartForceExitStatus",
1522 "SuccessExitStatus")) {
1523 _cleanup_free_ int *status = NULL, *signal = NULL;
1524 size_t n_status = 0, n_signal = 0;
1525 const char *p;
1526
1527 for (p = eq;;) {
1528 _cleanup_free_ char *word = NULL;
1529
1530 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
1531 if (r == 0)
1532 break;
1533 if (r == -ENOMEM)
1534 return log_oom();
1535 if (r < 0)
1536 return log_error_errno(r, "Invalid syntax in %s: %s", field, eq);
1537
1538 /* We need to call exit_status_from_string() first, because we want
1539 * to parse numbers as exit statuses, not signals. */
1540
1541 r = exit_status_from_string(word);
1542 if (r >= 0) {
1543 assert(r >= 0 && r < 256);
1544
1545 status = reallocarray(status, n_status + 1, sizeof(int));
1546 if (!status)
1547 return log_oom();
1548
1549 status[n_status++] = r;
1550
1551 } else if ((r = signal_from_string(word)) >= 0) {
1552 signal = reallocarray(signal, n_signal + 1, sizeof(int));
1553 if (!signal)
1554 return log_oom();
1555
1556 signal[n_signal++] = r;
1557
1558 } else
1559 /* original r from exit_status_to_string() */
1560 return log_error_errno(r, "Invalid status or signal %s in %s: %m",
1561 word, field);
1562 }
1563
1564 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1565 if (r < 0)
1566 return bus_log_create_error(r);
1567
1568 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1569 if (r < 0)
1570 return bus_log_create_error(r);
1571
1572 r = sd_bus_message_open_container(m, 'v', "(aiai)");
1573 if (r < 0)
1574 return bus_log_create_error(r);
1575
1576 r = sd_bus_message_open_container(m, 'r', "aiai");
1577 if (r < 0)
1578 return bus_log_create_error(r);
1579
1580 r = sd_bus_message_append_array(m, 'i', status, n_status * sizeof(int));
1581 if (r < 0)
1582 return bus_log_create_error(r);
1583
1584 r = sd_bus_message_append_array(m, 'i', signal, n_signal * sizeof(int));
1585 if (r < 0)
1586 return bus_log_create_error(r);
1587
1588 r = sd_bus_message_close_container(m);
1589 if (r < 0)
1590 return bus_log_create_error(r);
1591
1592 r = sd_bus_message_close_container(m);
1593 if (r < 0)
1594 return bus_log_create_error(r);
1595
1596 r = sd_bus_message_close_container(m);
1597 if (r < 0)
1598 return bus_log_create_error(r);
1599
1600 return 1;
1601 }
1602
1603 return 0;
1604 }
1605
1606 static int bus_append_socket_property(sd_bus_message *m, const char *field, const char *eq) {
1607 int r;
1608
1609 if (STR_IN_SET(field, "Accept",
1610 "Writable",
1611 "KeepAlive",
1612 "NoDelay",
1613 "FreeBind",
1614 "Transparent",
1615 "Broadcast",
1616 "PassCredentials",
1617 "PassSecurity",
1618 "ReusePort",
1619 "RemoveOnStop",
1620 "SELinuxContextFromNet"))
1621 return bus_append_parse_boolean(m, field, eq);
1622
1623 if (STR_IN_SET(field, "Priority",
1624 "IPTTL",
1625 "Mark"))
1626 return bus_append_safe_atoi(m, field, eq);
1627
1628 if (streq(field, "IPTOS"))
1629 return bus_append_ip_tos_from_string(m, field, eq);
1630
1631 if (STR_IN_SET(field, "Backlog",
1632 "MaxConnections",
1633 "MaxConnectionsPerSource",
1634 "KeepAliveProbes",
1635 "TriggerLimitBurst"))
1636 return bus_append_safe_atou(m, field, eq);
1637
1638 if (STR_IN_SET(field, "SocketMode",
1639 "DirectoryMode"))
1640 return bus_append_parse_mode(m, field, eq);
1641
1642 if (STR_IN_SET(field, "MessageQueueMaxMessages",
1643 "MessageQueueMessageSize"))
1644 return bus_append_safe_atoi64(m, field, eq);
1645
1646 if (STR_IN_SET(field, "TimeoutSec",
1647 "KeepAliveTimeSec",
1648 "KeepAliveIntervalSec",
1649 "DeferAcceptSec",
1650 "TriggerLimitIntervalSec"))
1651 return bus_append_parse_sec_rename(m, field, eq);
1652
1653 if (STR_IN_SET(field, "ReceiveBuffer",
1654 "SendBuffer",
1655 "PipeSize"))
1656 return bus_append_parse_size(m, field, eq, 1024);
1657
1658 if (STR_IN_SET(field, "ExecStartPre",
1659 "ExecStartPost",
1660 "ExecReload",
1661 "ExecStopPost"))
1662 return bus_append_exec_command(m, field, eq);
1663
1664 if (STR_IN_SET(field, "SmackLabel",
1665 "SmackLabelIPIn",
1666 "SmackLabelIPOut",
1667 "TCPCongestion",
1668 "BindToDevice",
1669 "BindIPv6Only",
1670 "FileDescriptorName",
1671 "SocketUser",
1672 "SocketGroup"))
1673 return bus_append_string(m, field, eq);
1674
1675 if (streq(field, "Symlinks"))
1676 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
1677
1678 if (streq(field, "SocketProtocol"))
1679 return bus_append_parse_ip_protocol(m, field, eq);
1680
1681 if (STR_IN_SET(field, "ListenStream",
1682 "ListenDatagram",
1683 "ListenSequentialPacket",
1684 "ListenNetlink",
1685 "ListenSpecial",
1686 "ListenMessageQueue",
1687 "ListenFIFO",
1688 "ListenUSBFunction")) {
1689 if (isempty(eq))
1690 r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 0);
1691 else
1692 r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 1, field + STRLEN("Listen"), eq);
1693 if (r < 0)
1694 return bus_log_create_error(r);
1695
1696 return 1;
1697 }
1698
1699 return 0;
1700 }
1701 static int bus_append_timer_property(sd_bus_message *m, const char *field, const char *eq) {
1702 int r;
1703
1704 if (STR_IN_SET(field, "WakeSystem",
1705 "RemainAfterElapse",
1706 "Persistent",
1707 "OnTimezoneChange",
1708 "OnClockChange"))
1709 return bus_append_parse_boolean(m, field, eq);
1710
1711 if (STR_IN_SET(field, "AccuracySec",
1712 "RandomizedDelaySec"))
1713 return bus_append_parse_sec_rename(m, field, eq);
1714
1715 if (STR_IN_SET(field, "OnActiveSec",
1716 "OnBootSec",
1717 "OnStartupSec",
1718 "OnUnitActiveSec",
1719 "OnUnitInactiveSec")) {
1720 if (isempty(eq))
1721 r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 0);
1722 else {
1723 usec_t t;
1724 r = parse_sec(eq, &t);
1725 if (r < 0)
1726 return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq);
1727
1728 r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 1, field, t);
1729 }
1730 if (r < 0)
1731 return bus_log_create_error(r);
1732
1733 return 1;
1734 }
1735
1736 if (streq(field, "OnCalendar")) {
1737 if (isempty(eq))
1738 r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 0);
1739 else
1740 r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 1, field, eq);
1741 if (r < 0)
1742 return bus_log_create_error(r);
1743
1744 return 1;
1745 }
1746
1747 return 0;
1748 }
1749
1750 static int bus_append_unit_property(sd_bus_message *m, const char *field, const char *eq) {
1751 ConditionType t = _CONDITION_TYPE_INVALID;
1752 bool is_condition = false;
1753 int r;
1754
1755 if (STR_IN_SET(field, "Description",
1756 "SourcePath",
1757 "OnFailureJobMode",
1758 "JobTimeoutAction",
1759 "JobTimeoutRebootArgument",
1760 "StartLimitAction",
1761 "FailureAction",
1762 "SuccessAction",
1763 "RebootArgument",
1764 "CollectMode"))
1765 return bus_append_string(m, field, eq);
1766
1767 if (STR_IN_SET(field, "StopWhenUnneeded",
1768 "RefuseManualStart",
1769 "RefuseManualStop",
1770 "AllowIsolate",
1771 "IgnoreOnIsolate",
1772 "DefaultDependencies"))
1773 return bus_append_parse_boolean(m, field, eq);
1774
1775 if (STR_IN_SET(field, "JobTimeoutSec",
1776 "JobRunningTimeoutSec",
1777 "StartLimitIntervalSec"))
1778 return bus_append_parse_sec_rename(m, field, eq);
1779
1780 if (streq(field, "StartLimitBurst"))
1781 return bus_append_safe_atou(m, field, eq);
1782
1783 if (STR_IN_SET(field, "SuccessActionExitStatus",
1784 "FailureActionExitStatus")) {
1785 if (isempty(eq))
1786 r = sd_bus_message_append(m, "(sv)", field, "i", -1);
1787 else {
1788 uint8_t u;
1789
1790 r = safe_atou8(eq, &u);
1791 if (r < 0)
1792 return log_error_errno(r, "Failed to parse %s=%s", field, eq);
1793
1794 r = sd_bus_message_append(m, "(sv)", field, "i", (int) u);
1795 }
1796 if (r < 0)
1797 return bus_log_create_error(r);
1798
1799 return 1;
1800 }
1801
1802 if (unit_dependency_from_string(field) >= 0 ||
1803 STR_IN_SET(field, "Documentation",
1804 "RequiresMountsFor"))
1805 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
1806
1807 t = condition_type_from_string(field);
1808 if (t >= 0)
1809 is_condition = true;
1810 else
1811 t = assert_type_from_string(field);
1812 if (t >= 0) {
1813 if (isempty(eq))
1814 r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 0);
1815 else {
1816 const char *p = eq;
1817 int trigger, negate;
1818
1819 trigger = *p == '|';
1820 if (trigger)
1821 p++;
1822
1823 negate = *p == '!';
1824 if (negate)
1825 p++;
1826
1827 r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 1,
1828 field, trigger, negate, p);
1829 }
1830 if (r < 0)
1831 return bus_log_create_error(r);
1832
1833 return 1;
1834 }
1835
1836 return 0;
1837 }
1838
1839 int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const char *assignment) {
1840 const char *eq, *field;
1841 int r;
1842
1843 assert(m);
1844 assert(assignment);
1845
1846 eq = strchr(assignment, '=');
1847 if (!eq)
1848 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1849 "Not an assignment: %s", assignment);
1850
1851 field = strndupa(assignment, eq - assignment);
1852 eq++;
1853
1854 switch (t) {
1855 case UNIT_SERVICE:
1856 r = bus_append_cgroup_property(m, field, eq);
1857 if (r != 0)
1858 return r;
1859
1860 r = bus_append_execute_property(m, field, eq);
1861 if (r != 0)
1862 return r;
1863
1864 r = bus_append_kill_property(m, field, eq);
1865 if (r != 0)
1866 return r;
1867
1868 r = bus_append_service_property(m, field, eq);
1869 if (r != 0)
1870 return r;
1871 break;
1872
1873 case UNIT_SOCKET:
1874 r = bus_append_cgroup_property(m, field, eq);
1875 if (r != 0)
1876 return r;
1877
1878 r = bus_append_execute_property(m, field, eq);
1879 if (r != 0)
1880 return r;
1881
1882 r = bus_append_kill_property(m, field, eq);
1883 if (r != 0)
1884 return r;
1885
1886 r = bus_append_socket_property(m, field, eq);
1887 if (r != 0)
1888 return r;
1889 break;
1890
1891 case UNIT_TIMER:
1892 r = bus_append_timer_property(m, field, eq);
1893 if (r != 0)
1894 return r;
1895 break;
1896
1897 case UNIT_PATH:
1898 r = bus_append_path_property(m, field, eq);
1899 if (r != 0)
1900 return r;
1901 break;
1902
1903 case UNIT_SLICE:
1904 r = bus_append_cgroup_property(m, field, eq);
1905 if (r != 0)
1906 return r;
1907 break;
1908
1909 case UNIT_SCOPE:
1910 r = bus_append_cgroup_property(m, field, eq);
1911 if (r != 0)
1912 return r;
1913
1914 r = bus_append_kill_property(m, field, eq);
1915 if (r != 0)
1916 return r;
1917
1918 r = bus_append_scope_property(m, field, eq);
1919 if (r != 0)
1920 return r;
1921 break;
1922
1923 case UNIT_MOUNT:
1924 r = bus_append_cgroup_property(m, field, eq);
1925 if (r != 0)
1926 return r;
1927
1928 r = bus_append_execute_property(m, field, eq);
1929 if (r != 0)
1930 return r;
1931
1932 r = bus_append_kill_property(m, field, eq);
1933 if (r != 0)
1934 return r;
1935
1936 r = bus_append_mount_property(m, field, eq);
1937 if (r != 0)
1938 return r;
1939
1940 break;
1941
1942 case UNIT_AUTOMOUNT:
1943 r = bus_append_automount_property(m, field, eq);
1944 if (r != 0)
1945 return r;
1946
1947 break;
1948
1949 case UNIT_TARGET:
1950 case UNIT_DEVICE:
1951 case UNIT_SWAP:
1952 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1953 "Not supported unit type");
1954
1955 default:
1956 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1957 "Invalid unit type");
1958 }
1959
1960 r = bus_append_unit_property(m, field, eq);
1961 if (r != 0)
1962 return r;
1963
1964 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1965 "Unknown assignment: %s", assignment);
1966 }
1967
1968 int bus_append_unit_property_assignment_many(sd_bus_message *m, UnitType t, char **l) {
1969 char **i;
1970 int r;
1971
1972 assert(m);
1973
1974 STRV_FOREACH(i, l) {
1975 r = bus_append_unit_property_assignment(m, t, *i);
1976 if (r < 0)
1977 return r;
1978 }
1979
1980 return 0;
1981 }
1982
1983 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes) {
1984 const char *type, *path, *source;
1985 int r;
1986
1987 /* changes is dereferenced when calling unit_file_dump_changes() later,
1988 * so we have to make sure this is not NULL. */
1989 assert(changes);
1990 assert(n_changes);
1991
1992 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1993 if (r < 0)
1994 return bus_log_parse_error(r);
1995
1996 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1997 /* We expect only "success" changes to be sent over the bus.
1998 Hence, reject anything negative. */
1999 UnitFileChangeType ch = unit_file_change_type_from_string(type);
2000
2001 if (ch < 0) {
2002 log_notice("Manager reported unknown change type \"%s\" for path \"%s\", ignoring.", type, path);
2003 continue;
2004 }
2005
2006 r = unit_file_changes_add(changes, n_changes, ch, path, source);
2007 if (r < 0)
2008 return r;
2009 }
2010 if (r < 0)
2011 return bus_log_parse_error(r);
2012
2013 r = sd_bus_message_exit_container(m);
2014 if (r < 0)
2015 return bus_log_parse_error(r);
2016
2017 unit_file_dump_changes(0, NULL, *changes, *n_changes, quiet);
2018 return 0;
2019 }
2020
2021 int unit_load_state(sd_bus *bus, const char *name, char **load_state) {
2022 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2023 _cleanup_free_ char *path = NULL;
2024 int r;
2025
2026 path = unit_dbus_path_from_name(name);
2027 if (!path)
2028 return log_oom();
2029
2030 /* This function warns on it's own, because otherwise it'd be awkward to pass
2031 * the dbus error message around. */
2032
2033 r = sd_bus_get_property_string(
2034 bus,
2035 "org.freedesktop.systemd1",
2036 path,
2037 "org.freedesktop.systemd1.Unit",
2038 "LoadState",
2039 &error,
2040 load_state);
2041 if (r < 0)
2042 return log_error_errno(r, "Failed to get load state of %s: %s", name, bus_error_message(&error, r));
2043
2044 return 0;
2045 }