]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-cgroup.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <arpa/inet.h>
22
23 #include "af-list.h"
24 #include "alloc-util.h"
25 #include "bpf-firewall.h"
26 #include "bus-util.h"
27 #include "cgroup-util.h"
28 #include "cgroup.h"
29 #include "dbus-cgroup.h"
30 #include "fd-util.h"
31 #include "fileio.h"
32 #include "path-util.h"
33
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
35
36 static int property_get_delegate_controllers(
37 sd_bus *bus,
38 const char *path,
39 const char *interface,
40 const char *property,
41 sd_bus_message *reply,
42 void *userdata,
43 sd_bus_error *error) {
44
45 CGroupContext *c = userdata;
46 CGroupController cc;
47 int r;
48
49 assert(bus);
50 assert(reply);
51 assert(c);
52
53 if (!c->delegate)
54 return sd_bus_message_append(reply, "as", 0);
55
56 r = sd_bus_message_open_container(reply, 'a', "s");
57 if (r < 0)
58 return r;
59
60 for (cc = 0; cc < _CGROUP_CONTROLLER_MAX; cc++) {
61 if ((c->delegate_controllers & CGROUP_CONTROLLER_TO_MASK(cc)) == 0)
62 continue;
63
64 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(cc));
65 if (r < 0)
66 return r;
67 }
68
69 return sd_bus_message_close_container(reply);
70 }
71
72 static int property_get_io_device_weight(
73 sd_bus *bus,
74 const char *path,
75 const char *interface,
76 const char *property,
77 sd_bus_message *reply,
78 void *userdata,
79 sd_bus_error *error) {
80
81 CGroupContext *c = userdata;
82 CGroupIODeviceWeight *w;
83 int r;
84
85 assert(bus);
86 assert(reply);
87 assert(c);
88
89 r = sd_bus_message_open_container(reply, 'a', "(st)");
90 if (r < 0)
91 return r;
92
93 LIST_FOREACH(device_weights, w, c->io_device_weights) {
94 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
95 if (r < 0)
96 return r;
97 }
98
99 return sd_bus_message_close_container(reply);
100 }
101
102 static int property_get_io_device_limits(
103 sd_bus *bus,
104 const char *path,
105 const char *interface,
106 const char *property,
107 sd_bus_message *reply,
108 void *userdata,
109 sd_bus_error *error) {
110
111 CGroupContext *c = userdata;
112 CGroupIODeviceLimit *l;
113 int r;
114
115 assert(bus);
116 assert(reply);
117 assert(c);
118
119 r = sd_bus_message_open_container(reply, 'a', "(st)");
120 if (r < 0)
121 return r;
122
123 LIST_FOREACH(device_limits, l, c->io_device_limits) {
124 CGroupIOLimitType type;
125
126 type = cgroup_io_limit_type_from_string(property);
127 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
128 continue;
129
130 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
131 if (r < 0)
132 return r;
133 }
134
135 return sd_bus_message_close_container(reply);
136 }
137
138 static int property_get_blockio_device_weight(
139 sd_bus *bus,
140 const char *path,
141 const char *interface,
142 const char *property,
143 sd_bus_message *reply,
144 void *userdata,
145 sd_bus_error *error) {
146
147 CGroupContext *c = userdata;
148 CGroupBlockIODeviceWeight *w;
149 int r;
150
151 assert(bus);
152 assert(reply);
153 assert(c);
154
155 r = sd_bus_message_open_container(reply, 'a', "(st)");
156 if (r < 0)
157 return r;
158
159 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
160 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
161 if (r < 0)
162 return r;
163 }
164
165 return sd_bus_message_close_container(reply);
166 }
167
168 static int property_get_blockio_device_bandwidths(
169 sd_bus *bus,
170 const char *path,
171 const char *interface,
172 const char *property,
173 sd_bus_message *reply,
174 void *userdata,
175 sd_bus_error *error) {
176
177 CGroupContext *c = userdata;
178 CGroupBlockIODeviceBandwidth *b;
179 int r;
180
181 assert(bus);
182 assert(reply);
183 assert(c);
184
185 r = sd_bus_message_open_container(reply, 'a', "(st)");
186 if (r < 0)
187 return r;
188
189 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
190 uint64_t v;
191
192 if (streq(property, "BlockIOReadBandwidth"))
193 v = b->rbps;
194 else
195 v = b->wbps;
196
197 if (v == CGROUP_LIMIT_MAX)
198 continue;
199
200 r = sd_bus_message_append(reply, "(st)", b->path, v);
201 if (r < 0)
202 return r;
203 }
204
205 return sd_bus_message_close_container(reply);
206 }
207
208 static int property_get_device_allow(
209 sd_bus *bus,
210 const char *path,
211 const char *interface,
212 const char *property,
213 sd_bus_message *reply,
214 void *userdata,
215 sd_bus_error *error) {
216
217 CGroupContext *c = userdata;
218 CGroupDeviceAllow *a;
219 int r;
220
221 assert(bus);
222 assert(reply);
223 assert(c);
224
225 r = sd_bus_message_open_container(reply, 'a', "(ss)");
226 if (r < 0)
227 return r;
228
229 LIST_FOREACH(device_allow, a, c->device_allow) {
230 unsigned k = 0;
231 char rwm[4];
232
233 if (a->r)
234 rwm[k++] = 'r';
235 if (a->w)
236 rwm[k++] = 'w';
237 if (a->m)
238 rwm[k++] = 'm';
239
240 rwm[k] = 0;
241
242 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
243 if (r < 0)
244 return r;
245 }
246
247 return sd_bus_message_close_container(reply);
248 }
249
250 static int property_get_ip_address_access(
251 sd_bus *bus,
252 const char *path,
253 const char *interface,
254 const char *property,
255 sd_bus_message *reply,
256 void *userdata,
257 sd_bus_error *error) {
258
259 IPAddressAccessItem** items = userdata, *i;
260 int r;
261
262 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
263 if (r < 0)
264 return r;
265
266 LIST_FOREACH(items, i, *items) {
267
268 r = sd_bus_message_open_container(reply, 'r', "iayu");
269 if (r < 0)
270 return r;
271
272 r = sd_bus_message_append(reply, "i", i->family);
273 if (r < 0)
274 return r;
275
276 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
277 if (r < 0)
278 return r;
279
280 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
281 if (r < 0)
282 return r;
283
284 r = sd_bus_message_close_container(reply);
285 if (r < 0)
286 return r;
287 }
288
289 return sd_bus_message_close_container(reply);
290 }
291
292 const sd_bus_vtable bus_cgroup_vtable[] = {
293 SD_BUS_VTABLE_START(0),
294 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
295 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
296 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
297 SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
298 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
299 SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
300 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
301 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
302 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
303 SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
304 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
305 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
306 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
307 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
308 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
309 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
310 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
311 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
312 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
313 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
314 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
315 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
316 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
317 SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
318 SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
319 SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
320 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
321 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
322 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
323 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
324 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
325 SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
326 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
327 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
328 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
329 SD_BUS_VTABLE_END
330 };
331
332 static int bus_cgroup_set_transient_property(
333 Unit *u,
334 CGroupContext *c,
335 const char *name,
336 sd_bus_message *message,
337 UnitSetPropertiesMode mode,
338 sd_bus_error *error) {
339
340 int r;
341
342 assert(u);
343 assert(c);
344 assert(name);
345 assert(message);
346
347 if (streq(name, "Delegate")) {
348 int b;
349
350 r = sd_bus_message_read(message, "b", &b);
351 if (r < 0)
352 return r;
353
354 if (mode != UNIT_CHECK) {
355 c->delegate = b;
356 c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
357
358 unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
359 }
360
361 return 1;
362
363 } else if (streq(name, "DelegateControllers")) {
364 CGroupMask mask = 0;
365
366 r = sd_bus_message_enter_container(message, 'a', "s");
367 if (r < 0)
368 return r;
369
370 for (;;) {
371 CGroupController cc;
372 const char *t;
373
374 r = sd_bus_message_read(message, "s", &t);
375 if (r < 0)
376 return r;
377 if (r == 0)
378 break;
379
380 cc = cgroup_controller_from_string(t);
381 if (cc < 0)
382 return sd_bus_error_set_errnof(error, EINVAL, "Unknown cgroup contoller '%s'", t);
383
384 mask |= CGROUP_CONTROLLER_TO_MASK(cc);
385 }
386
387 r = sd_bus_message_exit_container(message);
388 if (r < 0)
389 return r;
390
391 if (mode != UNIT_CHECK) {
392 _cleanup_free_ char *t = NULL;
393
394 r = cg_mask_to_string(mask, &t);
395 if (r < 0)
396 return r;
397
398 c->delegate = true;
399 if (mask == 0)
400 c->delegate_controllers = 0;
401 else
402 c->delegate_controllers |= mask;
403
404 unit_write_drop_in_private_format(u, mode, name, "Delegate=%s", strempty(t));
405 }
406
407 return 1;
408 }
409
410 return 0;
411 }
412
413 int bus_cgroup_set_property(
414 Unit *u,
415 CGroupContext *c,
416 const char *name,
417 sd_bus_message *message,
418 UnitSetPropertiesMode mode,
419 sd_bus_error *error) {
420
421 CGroupIOLimitType iol_type;
422 int r;
423
424 assert(u);
425 assert(c);
426 assert(name);
427 assert(message);
428
429 if (streq(name, "CPUAccounting")) {
430 int b;
431
432 r = sd_bus_message_read(message, "b", &b);
433 if (r < 0)
434 return r;
435
436 if (mode != UNIT_CHECK) {
437 c->cpu_accounting = b;
438 unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU);
439 unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
440 }
441
442 return 1;
443
444 } else if (streq(name, "CPUWeight")) {
445 uint64_t weight;
446
447 r = sd_bus_message_read(message, "t", &weight);
448 if (r < 0)
449 return r;
450
451 if (!CGROUP_WEIGHT_IS_OK(weight))
452 return sd_bus_error_set_errnof(error, EINVAL, "CPUWeight value out of range");
453
454 if (mode != UNIT_CHECK) {
455 c->cpu_weight = weight;
456 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
457
458 if (weight == CGROUP_WEIGHT_INVALID)
459 unit_write_drop_in_private(u, mode, name, "CPUWeight=");
460 else
461 unit_write_drop_in_private_format(u, mode, name, "CPUWeight=%" PRIu64, weight);
462 }
463
464 return 1;
465
466 } else if (streq(name, "StartupCPUWeight")) {
467 uint64_t weight;
468
469 r = sd_bus_message_read(message, "t", &weight);
470 if (r < 0)
471 return r;
472
473 if (!CGROUP_WEIGHT_IS_OK(weight))
474 return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUWeight value out of range");
475
476 if (mode != UNIT_CHECK) {
477 c->startup_cpu_weight = weight;
478 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
479
480 if (weight == CGROUP_CPU_SHARES_INVALID)
481 unit_write_drop_in_private(u, mode, name, "StartupCPUWeight=");
482 else
483 unit_write_drop_in_private_format(u, mode, name, "StartupCPUWeight=%" PRIu64, weight);
484 }
485
486 return 1;
487
488 } else if (streq(name, "CPUShares")) {
489 uint64_t shares;
490
491 r = sd_bus_message_read(message, "t", &shares);
492 if (r < 0)
493 return r;
494
495 if (!CGROUP_CPU_SHARES_IS_OK(shares))
496 return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
497
498 if (mode != UNIT_CHECK) {
499 c->cpu_shares = shares;
500 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
501
502 if (shares == CGROUP_CPU_SHARES_INVALID)
503 unit_write_drop_in_private(u, mode, name, "CPUShares=");
504 else
505 unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
506 }
507
508 return 1;
509
510 } else if (streq(name, "StartupCPUShares")) {
511 uint64_t shares;
512
513 r = sd_bus_message_read(message, "t", &shares);
514 if (r < 0)
515 return r;
516
517 if (!CGROUP_CPU_SHARES_IS_OK(shares))
518 return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
519
520 if (mode != UNIT_CHECK) {
521 c->startup_cpu_shares = shares;
522 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
523
524 if (shares == CGROUP_CPU_SHARES_INVALID)
525 unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
526 else
527 unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
528 }
529
530 return 1;
531
532 } else if (streq(name, "CPUQuotaPerSecUSec")) {
533 uint64_t u64;
534
535 r = sd_bus_message_read(message, "t", &u64);
536 if (r < 0)
537 return r;
538
539 if (u64 <= 0)
540 return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
541
542 if (mode != UNIT_CHECK) {
543 c->cpu_quota_per_sec_usec = u64;
544 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
545 if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
546 unit_write_drop_in_private_format(u, mode, "CPUQuota",
547 "CPUQuota=");
548 else
549 /* config_parse_cpu_quota() requires an integer, so
550 * truncating division is used on purpose here. */
551 unit_write_drop_in_private_format(u, mode, "CPUQuota",
552 "CPUQuota=%0.f%%",
553 (double) (c->cpu_quota_per_sec_usec / 10000));
554 }
555
556 return 1;
557
558 } else if (streq(name, "IOAccounting")) {
559 int b;
560
561 r = sd_bus_message_read(message, "b", &b);
562 if (r < 0)
563 return r;
564
565 if (mode != UNIT_CHECK) {
566 c->io_accounting = b;
567 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
568 unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes" : "IOAccounting=no");
569 }
570
571 return 1;
572
573 } else if (streq(name, "IOWeight")) {
574 uint64_t weight;
575
576 r = sd_bus_message_read(message, "t", &weight);
577 if (r < 0)
578 return r;
579
580 if (!CGROUP_WEIGHT_IS_OK(weight))
581 return sd_bus_error_set_errnof(error, EINVAL, "IOWeight value out of range");
582
583 if (mode != UNIT_CHECK) {
584 c->io_weight = weight;
585 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
586
587 if (weight == CGROUP_WEIGHT_INVALID)
588 unit_write_drop_in_private(u, mode, name, "IOWeight=");
589 else
590 unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64, weight);
591 }
592
593 return 1;
594
595 } else if (streq(name, "StartupIOWeight")) {
596 uint64_t weight;
597
598 r = sd_bus_message_read(message, "t", &weight);
599 if (r < 0)
600 return r;
601
602 if (CGROUP_WEIGHT_IS_OK(weight))
603 return sd_bus_error_set_errnof(error, EINVAL, "StartupIOWeight value out of range");
604
605 if (mode != UNIT_CHECK) {
606 c->startup_io_weight = weight;
607 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
608
609 if (weight == CGROUP_WEIGHT_INVALID)
610 unit_write_drop_in_private(u, mode, name, "StartupIOWeight=");
611 else
612 unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64, weight);
613 }
614
615 return 1;
616
617 } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
618 const char *path;
619 unsigned n = 0;
620 uint64_t u64;
621
622 r = sd_bus_message_enter_container(message, 'a', "(st)");
623 if (r < 0)
624 return r;
625
626 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
627
628 if (mode != UNIT_CHECK) {
629 CGroupIODeviceLimit *a = NULL, *b;
630
631 LIST_FOREACH(device_limits, b, c->io_device_limits) {
632 if (path_equal(path, b->path)) {
633 a = b;
634 break;
635 }
636 }
637
638 if (!a) {
639 CGroupIOLimitType type;
640
641 a = new0(CGroupIODeviceLimit, 1);
642 if (!a)
643 return -ENOMEM;
644
645 a->path = strdup(path);
646 if (!a->path) {
647 free(a);
648 return -ENOMEM;
649 }
650
651 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
652 a->limits[type] = cgroup_io_limit_defaults[type];
653
654 LIST_PREPEND(device_limits, c->io_device_limits, a);
655 }
656
657 a->limits[iol_type] = u64;
658 }
659
660 n++;
661 }
662 if (r < 0)
663 return r;
664
665 r = sd_bus_message_exit_container(message);
666 if (r < 0)
667 return r;
668
669 if (mode != UNIT_CHECK) {
670 CGroupIODeviceLimit *a;
671 _cleanup_free_ char *buf = NULL;
672 _cleanup_fclose_ FILE *f = NULL;
673 size_t size = 0;
674
675 if (n == 0) {
676 LIST_FOREACH(device_limits, a, c->io_device_limits)
677 a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
678 }
679
680 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
681
682 f = open_memstream(&buf, &size);
683 if (!f)
684 return -ENOMEM;
685
686 fprintf(f, "%s=\n", name);
687 LIST_FOREACH(device_limits, a, c->io_device_limits)
688 if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
689 fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
690
691 r = fflush_and_check(f);
692 if (r < 0)
693 return r;
694 unit_write_drop_in_private(u, mode, name, buf);
695 }
696
697 return 1;
698
699 } else if (streq(name, "IODeviceWeight")) {
700 const char *path;
701 uint64_t weight;
702 unsigned n = 0;
703
704 r = sd_bus_message_enter_container(message, 'a', "(st)");
705 if (r < 0)
706 return r;
707
708 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
709
710 if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
711 return sd_bus_error_set_errnof(error, EINVAL, "IODeviceWeight out of range");
712
713 if (mode != UNIT_CHECK) {
714 CGroupIODeviceWeight *a = NULL, *b;
715
716 LIST_FOREACH(device_weights, b, c->io_device_weights) {
717 if (path_equal(b->path, path)) {
718 a = b;
719 break;
720 }
721 }
722
723 if (!a) {
724 a = new0(CGroupIODeviceWeight, 1);
725 if (!a)
726 return -ENOMEM;
727
728 a->path = strdup(path);
729 if (!a->path) {
730 free(a);
731 return -ENOMEM;
732 }
733 LIST_PREPEND(device_weights,c->io_device_weights, a);
734 }
735
736 a->weight = weight;
737 }
738
739 n++;
740 }
741
742 r = sd_bus_message_exit_container(message);
743 if (r < 0)
744 return r;
745
746 if (mode != UNIT_CHECK) {
747 _cleanup_free_ char *buf = NULL;
748 _cleanup_fclose_ FILE *f = NULL;
749 CGroupIODeviceWeight *a;
750 size_t size = 0;
751
752 if (n == 0) {
753 while (c->io_device_weights)
754 cgroup_context_free_io_device_weight(c, c->io_device_weights);
755 }
756
757 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
758
759 f = open_memstream(&buf, &size);
760 if (!f)
761 return -ENOMEM;
762
763 fputs_unlocked("IODeviceWeight=\n", f);
764 LIST_FOREACH(device_weights, a, c->io_device_weights)
765 fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
766
767 r = fflush_and_check(f);
768 if (r < 0)
769 return r;
770 unit_write_drop_in_private(u, mode, name, buf);
771 }
772
773 return 1;
774
775 } else if (streq(name, "BlockIOAccounting")) {
776 int b;
777
778 r = sd_bus_message_read(message, "b", &b);
779 if (r < 0)
780 return r;
781
782 if (mode != UNIT_CHECK) {
783 c->blockio_accounting = b;
784 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
785 unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
786 }
787
788 return 1;
789
790 } else if (streq(name, "BlockIOWeight")) {
791 uint64_t weight;
792
793 r = sd_bus_message_read(message, "t", &weight);
794 if (r < 0)
795 return r;
796
797 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
798 return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
799
800 if (mode != UNIT_CHECK) {
801 c->blockio_weight = weight;
802 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
803
804 if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
805 unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
806 else
807 unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
808 }
809
810 return 1;
811
812 } else if (streq(name, "StartupBlockIOWeight")) {
813 uint64_t weight;
814
815 r = sd_bus_message_read(message, "t", &weight);
816 if (r < 0)
817 return r;
818
819 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
820 return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
821
822 if (mode != UNIT_CHECK) {
823 c->startup_blockio_weight = weight;
824 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
825
826 if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
827 unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
828 else
829 unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
830 }
831
832 return 1;
833
834 } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
835 const char *path;
836 bool read = true;
837 unsigned n = 0;
838 uint64_t u64;
839
840 if (streq(name, "BlockIOWriteBandwidth"))
841 read = false;
842
843 r = sd_bus_message_enter_container(message, 'a', "(st)");
844 if (r < 0)
845 return r;
846
847 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
848
849 if (mode != UNIT_CHECK) {
850 CGroupBlockIODeviceBandwidth *a = NULL, *b;
851
852 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
853 if (path_equal(path, b->path)) {
854 a = b;
855 break;
856 }
857 }
858
859 if (!a) {
860 a = new0(CGroupBlockIODeviceBandwidth, 1);
861 if (!a)
862 return -ENOMEM;
863
864 a->rbps = CGROUP_LIMIT_MAX;
865 a->wbps = CGROUP_LIMIT_MAX;
866 a->path = strdup(path);
867 if (!a->path) {
868 free(a);
869 return -ENOMEM;
870 }
871
872 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
873 }
874
875 if (read)
876 a->rbps = u64;
877 else
878 a->wbps = u64;
879 }
880
881 n++;
882 }
883 if (r < 0)
884 return r;
885
886 r = sd_bus_message_exit_container(message);
887 if (r < 0)
888 return r;
889
890 if (mode != UNIT_CHECK) {
891 CGroupBlockIODeviceBandwidth *a;
892 _cleanup_free_ char *buf = NULL;
893 _cleanup_fclose_ FILE *f = NULL;
894 size_t size = 0;
895
896 if (n == 0) {
897 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
898 if (read)
899 a->rbps = CGROUP_LIMIT_MAX;
900 else
901 a->wbps = CGROUP_LIMIT_MAX;
902 }
903 }
904
905 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
906
907 f = open_memstream(&buf, &size);
908 if (!f)
909 return -ENOMEM;
910
911 if (read) {
912 fputs_unlocked("BlockIOReadBandwidth=\n", f);
913 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
914 if (a->rbps != CGROUP_LIMIT_MAX)
915 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
916 } else {
917 fputs_unlocked("BlockIOWriteBandwidth=\n", f);
918 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
919 if (a->wbps != CGROUP_LIMIT_MAX)
920 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
921 }
922
923 r = fflush_and_check(f);
924 if (r < 0)
925 return r;
926 unit_write_drop_in_private(u, mode, name, buf);
927 }
928
929 return 1;
930
931 } else if (streq(name, "BlockIODeviceWeight")) {
932 const char *path;
933 uint64_t weight;
934 unsigned n = 0;
935
936 r = sd_bus_message_enter_container(message, 'a', "(st)");
937 if (r < 0)
938 return r;
939
940 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
941
942 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
943 return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
944
945 if (mode != UNIT_CHECK) {
946 CGroupBlockIODeviceWeight *a = NULL, *b;
947
948 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
949 if (path_equal(b->path, path)) {
950 a = b;
951 break;
952 }
953 }
954
955 if (!a) {
956 a = new0(CGroupBlockIODeviceWeight, 1);
957 if (!a)
958 return -ENOMEM;
959
960 a->path = strdup(path);
961 if (!a->path) {
962 free(a);
963 return -ENOMEM;
964 }
965 LIST_PREPEND(device_weights,c->blockio_device_weights, a);
966 }
967
968 a->weight = weight;
969 }
970
971 n++;
972 }
973
974 r = sd_bus_message_exit_container(message);
975 if (r < 0)
976 return r;
977
978 if (mode != UNIT_CHECK) {
979 _cleanup_free_ char *buf = NULL;
980 _cleanup_fclose_ FILE *f = NULL;
981 CGroupBlockIODeviceWeight *a;
982 size_t size = 0;
983
984 if (n == 0) {
985 while (c->blockio_device_weights)
986 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
987 }
988
989 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
990
991 f = open_memstream(&buf, &size);
992 if (!f)
993 return -ENOMEM;
994
995 fputs_unlocked("BlockIODeviceWeight=\n", f);
996 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
997 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
998
999 r = fflush_and_check(f);
1000 if (r < 0)
1001 return r;
1002 unit_write_drop_in_private(u, mode, name, buf);
1003 }
1004
1005 return 1;
1006
1007 } else if (streq(name, "MemoryAccounting")) {
1008 int b;
1009
1010 r = sd_bus_message_read(message, "b", &b);
1011 if (r < 0)
1012 return r;
1013
1014 if (mode != UNIT_CHECK) {
1015 c->memory_accounting = b;
1016 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
1017 unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
1018 }
1019
1020 return 1;
1021
1022 } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) {
1023 uint64_t v;
1024
1025 r = sd_bus_message_read(message, "t", &v);
1026 if (r < 0)
1027 return r;
1028 if (v <= 0)
1029 return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
1030
1031 if (mode != UNIT_CHECK) {
1032 if (streq(name, "MemoryLow"))
1033 c->memory_low = v;
1034 else if (streq(name, "MemoryHigh"))
1035 c->memory_high = v;
1036 else if (streq(name, "MemorySwapMax"))
1037 c->memory_swap_max = v;
1038 else
1039 c->memory_max = v;
1040
1041 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
1042
1043 if (v == CGROUP_LIMIT_MAX)
1044 unit_write_drop_in_private_format(u, mode, name, "%s=infinity", name);
1045 else
1046 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, v);
1047 }
1048
1049 return 1;
1050
1051 } else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) {
1052 uint32_t raw;
1053 uint64_t v;
1054
1055 r = sd_bus_message_read(message, "u", &raw);
1056 if (r < 0)
1057 return r;
1058
1059 v = physical_memory_scale(raw, UINT32_MAX);
1060 if (v <= 0 || v == UINT64_MAX)
1061 return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
1062
1063 if (mode != UNIT_CHECK) {
1064 const char *e;
1065
1066 /* Chop off suffix */
1067 assert_se(e = endswith(name, "Scale"));
1068 name = strndupa(name, e - name);
1069
1070 if (streq(name, "MemoryLow"))
1071 c->memory_low = v;
1072 else if (streq(name, "MemoryHigh"))
1073 c->memory_high = v;
1074 else
1075 c->memory_max = v;
1076
1077 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
1078 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name,
1079 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
1080 }
1081
1082 return 1;
1083
1084 } else if (streq(name, "MemoryLimit")) {
1085 uint64_t limit;
1086
1087 r = sd_bus_message_read(message, "t", &limit);
1088 if (r < 0)
1089 return r;
1090 if (limit <= 0)
1091 return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
1092
1093 if (mode != UNIT_CHECK) {
1094 c->memory_limit = limit;
1095 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
1096
1097 if (limit == (uint64_t) -1)
1098 unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
1099 else
1100 unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
1101 }
1102
1103 return 1;
1104
1105 } else if (streq(name, "MemoryLimitScale")) {
1106 uint64_t limit;
1107 uint32_t raw;
1108
1109 r = sd_bus_message_read(message, "u", &raw);
1110 if (r < 0)
1111 return r;
1112
1113 limit = physical_memory_scale(raw, UINT32_MAX);
1114 if (limit <= 0 || limit == UINT64_MAX)
1115 return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
1116
1117 if (mode != UNIT_CHECK) {
1118 c->memory_limit = limit;
1119 unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
1120 unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
1121 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
1122 }
1123
1124 return 1;
1125
1126 } else if (streq(name, "DevicePolicy")) {
1127 const char *policy;
1128 CGroupDevicePolicy p;
1129
1130 r = sd_bus_message_read(message, "s", &policy);
1131 if (r < 0)
1132 return r;
1133
1134 p = cgroup_device_policy_from_string(policy);
1135 if (p < 0)
1136 return -EINVAL;
1137
1138 if (mode != UNIT_CHECK) {
1139 c->device_policy = p;
1140 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1141 unit_write_drop_in_private_format(u, mode, name, "DevicePolicy=%s", policy);
1142 }
1143
1144 return 1;
1145
1146 } else if (streq(name, "DeviceAllow")) {
1147 const char *path, *rwm;
1148 unsigned n = 0;
1149
1150 r = sd_bus_message_enter_container(message, 'a', "(ss)");
1151 if (r < 0)
1152 return r;
1153
1154 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
1155
1156 if ((!path_startswith(path, "/dev/") &&
1157 !path_startswith(path, "/run/systemd/inaccessible/") &&
1158 !startswith(path, "block-") &&
1159 !startswith(path, "char-")) ||
1160 strpbrk(path, WHITESPACE))
1161 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
1162
1163 if (isempty(rwm))
1164 rwm = "rwm";
1165
1166 if (!in_charset(rwm, "rwm"))
1167 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
1168
1169 if (mode != UNIT_CHECK) {
1170 CGroupDeviceAllow *a = NULL, *b;
1171
1172 LIST_FOREACH(device_allow, b, c->device_allow) {
1173 if (path_equal(b->path, path)) {
1174 a = b;
1175 break;
1176 }
1177 }
1178
1179 if (!a) {
1180 a = new0(CGroupDeviceAllow, 1);
1181 if (!a)
1182 return -ENOMEM;
1183
1184 a->path = strdup(path);
1185 if (!a->path) {
1186 free(a);
1187 return -ENOMEM;
1188 }
1189
1190 LIST_PREPEND(device_allow, c->device_allow, a);
1191 }
1192
1193 a->r = !!strchr(rwm, 'r');
1194 a->w = !!strchr(rwm, 'w');
1195 a->m = !!strchr(rwm, 'm');
1196 }
1197
1198 n++;
1199 }
1200 if (r < 0)
1201 return r;
1202
1203 r = sd_bus_message_exit_container(message);
1204 if (r < 0)
1205 return r;
1206
1207 if (mode != UNIT_CHECK) {
1208 _cleanup_free_ char *buf = NULL;
1209 _cleanup_fclose_ FILE *f = NULL;
1210 CGroupDeviceAllow *a;
1211 size_t size = 0;
1212
1213 if (n == 0) {
1214 while (c->device_allow)
1215 cgroup_context_free_device_allow(c, c->device_allow);
1216 }
1217
1218 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1219
1220 f = open_memstream(&buf, &size);
1221 if (!f)
1222 return -ENOMEM;
1223
1224 fputs_unlocked("DeviceAllow=\n", f);
1225 LIST_FOREACH(device_allow, a, c->device_allow)
1226 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1227
1228 r = fflush_and_check(f);
1229 if (r < 0)
1230 return r;
1231 unit_write_drop_in_private(u, mode, name, buf);
1232 }
1233
1234 return 1;
1235
1236 } else if (streq(name, "TasksAccounting")) {
1237 int b;
1238
1239 r = sd_bus_message_read(message, "b", &b);
1240 if (r < 0)
1241 return r;
1242
1243 if (mode != UNIT_CHECK) {
1244 c->tasks_accounting = b;
1245 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
1246 unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
1247 }
1248
1249 return 1;
1250
1251 } else if (streq(name, "TasksMax")) {
1252 uint64_t limit;
1253
1254 r = sd_bus_message_read(message, "t", &limit);
1255 if (r < 0)
1256 return r;
1257 if (limit <= 0)
1258 return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
1259
1260 if (mode != UNIT_CHECK) {
1261 c->tasks_max = limit;
1262 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
1263
1264 if (limit == (uint64_t) -1)
1265 unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
1266 else
1267 unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
1268 }
1269
1270 return 1;
1271
1272 } else if (streq(name, "TasksMaxScale")) {
1273 uint64_t limit;
1274 uint32_t raw;
1275
1276 r = sd_bus_message_read(message, "u", &raw);
1277 if (r < 0)
1278 return r;
1279
1280 limit = system_tasks_max_scale(raw, UINT32_MAX);
1281 if (limit <= 0 || limit >= UINT64_MAX)
1282 return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
1283
1284 if (mode != UNIT_CHECK) {
1285 c->tasks_max = limit;
1286 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
1287 unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu32 "%%",
1288 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
1289 }
1290
1291 return 1;
1292
1293 } else if (streq(name, "IPAccounting")) {
1294 int b;
1295
1296 r = sd_bus_message_read(message, "b", &b);
1297 if (r < 0)
1298 return r;
1299
1300 if (mode != UNIT_CHECK) {
1301 c->ip_accounting = b;
1302
1303 unit_invalidate_cgroup_bpf(u);
1304 unit_write_drop_in_private(u, mode, name, b ? "IPAccounting=yes" : "IPAccounting=no");
1305 }
1306
1307 return 1;
1308
1309 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1310 IPAddressAccessItem **list;
1311 size_t n = 0;
1312
1313 list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1314
1315 r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1316 if (r < 0)
1317 return r;
1318
1319 for (;;) {
1320 const void *ap;
1321 int32_t family;
1322 uint32_t prefixlen;
1323 size_t an;
1324
1325 r = sd_bus_message_enter_container(message, 'r', "iayu");
1326 if (r < 0)
1327 return r;
1328 if (r == 0)
1329 break;
1330
1331 r = sd_bus_message_read(message, "i", &family);
1332 if (r < 0)
1333 return r;
1334
1335 if (!IN_SET(family, AF_INET, AF_INET6))
1336 return sd_bus_error_set_errnof(error, EINVAL, "%s= expects IPv4 or IPv6 addresses only.", name);
1337
1338 r = sd_bus_message_read_array(message, 'y', &ap, &an);
1339 if (r < 0)
1340 return r;
1341
1342 if (an != FAMILY_ADDRESS_SIZE(family))
1343 return sd_bus_error_set_errnof(error, EINVAL, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1344 af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1345
1346 r = sd_bus_message_read(message, "u", &prefixlen);
1347 if (r < 0)
1348 return r;
1349
1350 if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
1351 return sd_bus_error_set_errnof(error, EINVAL, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
1352
1353 if (mode != UNIT_CHECK) {
1354 IPAddressAccessItem *item;
1355
1356 item = new0(IPAddressAccessItem, 1);
1357 if (!item)
1358 return -ENOMEM;
1359
1360 item->family = family;
1361 item->prefixlen = prefixlen;
1362 memcpy(&item->address, ap, an);
1363
1364 LIST_PREPEND(items, *list, item);
1365 }
1366
1367 r = sd_bus_message_exit_container(message);
1368 if (r < 0)
1369 return r;
1370
1371 n++;
1372 }
1373
1374 r = sd_bus_message_exit_container(message);
1375 if (r < 0)
1376 return r;
1377
1378 *list = ip_address_access_reduce(*list);
1379
1380 if (mode != UNIT_CHECK) {
1381 _cleanup_free_ char *buf = NULL;
1382 _cleanup_fclose_ FILE *f = NULL;
1383 IPAddressAccessItem *item;
1384 size_t size = 0;
1385
1386 if (n == 0)
1387 *list = ip_address_access_free_all(*list);
1388
1389 unit_invalidate_cgroup_bpf(u);
1390 f = open_memstream(&buf, &size);
1391 if (!f)
1392 return -ENOMEM;
1393
1394 fputs_unlocked(name, f);
1395 fputs_unlocked("=\n", f);
1396
1397 LIST_FOREACH(items, item, *list) {
1398 char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
1399
1400 errno = 0;
1401 if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
1402 return errno > 0 ? -errno : -EINVAL;
1403
1404 fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
1405 }
1406
1407 r = fflush_and_check(f);
1408 if (r < 0)
1409 return r;
1410 unit_write_drop_in_private(u, mode, name, buf);
1411
1412 if (*list) {
1413 r = bpf_firewall_supported();
1414 if (r < 0)
1415 return r;
1416 if (r == 0) {
1417 static bool warned = false;
1418
1419 log_full(warned ? LOG_DEBUG : LOG_WARNING,
1420 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1421 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
1422
1423 warned = true;
1424 }
1425 }
1426 }
1427
1428 return 1;
1429 }
1430
1431 if (u->transient && u->load_state == UNIT_STUB) {
1432 r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
1433 if (r != 0)
1434 return r;
1435
1436 }
1437
1438 return 0;
1439 }