]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-cgroup.c
Merge pull request #8143 from yuwata/drop-unused-func
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
4ad49000
LP
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
3dc5ca97 21#include <arpa/inet.h>
0d536673 22#include <stdio_ext.h>
3dc5ca97
LP
23
24#include "af-list.h"
b5efdb8a 25#include "alloc-util.h"
078ba556 26#include "bpf-firewall.h"
718db961 27#include "bus-util.h"
718db961
LP
28#include "cgroup-util.h"
29#include "cgroup.h"
4ad49000 30#include "dbus-cgroup.h"
681ae88e 31#include "dbus-util.h"
3ffd4af2 32#include "fd-util.h"
0d39fa9c 33#include "fileio.h"
3ffd4af2 34#include "path-util.h"
4ad49000 35
718db961
LP
36static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
37
02638280
LP
38static int property_get_delegate_controllers(
39 sd_bus *bus,
40 const char *path,
41 const char *interface,
42 const char *property,
43 sd_bus_message *reply,
44 void *userdata,
45 sd_bus_error *error) {
46
47 CGroupContext *c = userdata;
48 CGroupController cc;
49 int r;
50
51 assert(bus);
52 assert(reply);
53 assert(c);
54
55 if (!c->delegate)
56 return sd_bus_message_append(reply, "as", 0);
57
58 r = sd_bus_message_open_container(reply, 'a', "s");
59 if (r < 0)
60 return r;
61
62 for (cc = 0; cc < _CGROUP_CONTROLLER_MAX; cc++) {
63 if ((c->delegate_controllers & CGROUP_CONTROLLER_TO_MASK(cc)) == 0)
64 continue;
65
66 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(cc));
67 if (r < 0)
68 return r;
69 }
70
71 return sd_bus_message_close_container(reply);
72}
73
13c31542
TH
74static int property_get_io_device_weight(
75 sd_bus *bus,
76 const char *path,
77 const char *interface,
78 const char *property,
79 sd_bus_message *reply,
80 void *userdata,
81 sd_bus_error *error) {
82
83 CGroupContext *c = userdata;
84 CGroupIODeviceWeight *w;
85 int r;
86
87 assert(bus);
88 assert(reply);
89 assert(c);
90
91 r = sd_bus_message_open_container(reply, 'a', "(st)");
92 if (r < 0)
93 return r;
94
95 LIST_FOREACH(device_weights, w, c->io_device_weights) {
96 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
97 if (r < 0)
98 return r;
99 }
100
101 return sd_bus_message_close_container(reply);
102}
103
104static int property_get_io_device_limits(
105 sd_bus *bus,
106 const char *path,
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
110 void *userdata,
111 sd_bus_error *error) {
112
113 CGroupContext *c = userdata;
114 CGroupIODeviceLimit *l;
115 int r;
116
117 assert(bus);
118 assert(reply);
119 assert(c);
120
121 r = sd_bus_message_open_container(reply, 'a', "(st)");
122 if (r < 0)
123 return r;
124
125 LIST_FOREACH(device_limits, l, c->io_device_limits) {
9be57249 126 CGroupIOLimitType type;
13c31542 127
9be57249
TH
128 type = cgroup_io_limit_type_from_string(property);
129 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
13c31542
TH
130 continue;
131
9be57249 132 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
13c31542
TH
133 if (r < 0)
134 return r;
135 }
136
137 return sd_bus_message_close_container(reply);
138}
139
718db961
LP
140static int property_get_blockio_device_weight(
141 sd_bus *bus,
142 const char *path,
143 const char *interface,
144 const char *property,
145 sd_bus_message *reply,
ebcf1f97
LP
146 void *userdata,
147 sd_bus_error *error) {
4ad49000 148
718db961 149 CGroupContext *c = userdata;
4ad49000 150 CGroupBlockIODeviceWeight *w;
718db961 151 int r;
4ad49000 152
718db961
LP
153 assert(bus);
154 assert(reply);
4ad49000
LP
155 assert(c);
156
718db961
LP
157 r = sd_bus_message_open_container(reply, 'a', "(st)");
158 if (r < 0)
159 return r;
4ad49000
LP
160
161 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
718db961
LP
162 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
163 if (r < 0)
164 return r;
4ad49000
LP
165 }
166
718db961 167 return sd_bus_message_close_container(reply);
4ad49000
LP
168}
169
718db961
LP
170static int property_get_blockio_device_bandwidths(
171 sd_bus *bus,
172 const char *path,
173 const char *interface,
174 const char *property,
175 sd_bus_message *reply,
ebcf1f97
LP
176 void *userdata,
177 sd_bus_error *error) {
718db961
LP
178
179 CGroupContext *c = userdata;
4ad49000 180 CGroupBlockIODeviceBandwidth *b;
718db961 181 int r;
4ad49000 182
718db961
LP
183 assert(bus);
184 assert(reply);
4ad49000
LP
185 assert(c);
186
718db961
LP
187 r = sd_bus_message_open_container(reply, 'a', "(st)");
188 if (r < 0)
189 return r;
4ad49000
LP
190
191 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
979d0311 192 uint64_t v;
4ad49000 193
979d0311
TH
194 if (streq(property, "BlockIOReadBandwidth"))
195 v = b->rbps;
196 else
197 v = b->wbps;
198
199 if (v == CGROUP_LIMIT_MAX)
4ad49000
LP
200 continue;
201
979d0311 202 r = sd_bus_message_append(reply, "(st)", b->path, v);
718db961
LP
203 if (r < 0)
204 return r;
4ad49000
LP
205 }
206
718db961 207 return sd_bus_message_close_container(reply);
4ad49000
LP
208}
209
718db961
LP
210static int property_get_device_allow(
211 sd_bus *bus,
212 const char *path,
213 const char *interface,
214 const char *property,
215 sd_bus_message *reply,
ebcf1f97
LP
216 void *userdata,
217 sd_bus_error *error) {
718db961
LP
218
219 CGroupContext *c = userdata;
4ad49000 220 CGroupDeviceAllow *a;
718db961 221 int r;
4ad49000 222
718db961
LP
223 assert(bus);
224 assert(reply);
4ad49000
LP
225 assert(c);
226
718db961
LP
227 r = sd_bus_message_open_container(reply, 'a', "(ss)");
228 if (r < 0)
229 return r;
4ad49000
LP
230
231 LIST_FOREACH(device_allow, a, c->device_allow) {
4ad49000 232 unsigned k = 0;
718db961 233 char rwm[4];
4ad49000
LP
234
235 if (a->r)
718db961 236 rwm[k++] = 'r';
4ad49000 237 if (a->w)
718db961 238 rwm[k++] = 'w';
4ad49000 239 if (a->m)
718db961 240 rwm[k++] = 'm';
4ad49000 241
718db961 242 rwm[k] = 0;
4ad49000 243
718db961
LP
244 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
245 if (r < 0)
246 return r;
4ad49000
LP
247 }
248
718db961 249 return sd_bus_message_close_container(reply);
4ad49000
LP
250}
251
3dc5ca97
LP
252static int property_get_ip_address_access(
253 sd_bus *bus,
254 const char *path,
255 const char *interface,
256 const char *property,
257 sd_bus_message *reply,
258 void *userdata,
259 sd_bus_error *error) {
260
261 IPAddressAccessItem** items = userdata, *i;
262 int r;
263
264 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
265 if (r < 0)
266 return r;
267
268 LIST_FOREACH(items, i, *items) {
269
270 r = sd_bus_message_open_container(reply, 'r', "iayu");
271 if (r < 0)
272 return r;
273
274 r = sd_bus_message_append(reply, "i", i->family);
275 if (r < 0)
276 return r;
277
278 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
279 if (r < 0)
280 return r;
281
282 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
283 if (r < 0)
284 return r;
285
286 r = sd_bus_message_close_container(reply);
287 if (r < 0)
288 return r;
289 }
290
291 return sd_bus_message_close_container(reply);
292}
293
718db961
LP
294const sd_bus_vtable bus_cgroup_vtable[] = {
295 SD_BUS_VTABLE_START(0),
a931ad47 296 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
02638280 297 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
610f780c 298 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
66ebf6c0
TH
299 SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
300 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
d53d9474
LP
301 SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
302 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
ee26bcc0 303 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
13c31542
TH
304 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
305 SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
306 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
307 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
308 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
309 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
ac06a0cf
TH
310 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
311 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
610f780c 312 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
d53d9474
LP
313 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
314 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
610f780c
LP
315 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
316 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
317 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
318 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
da4d897e
TH
319 SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
320 SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
321 SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
96e131ea 322 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
610f780c
LP
323 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
324 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
325 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
03a7b521
LP
326 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
327 SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
3dc5ca97
LP
328 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
329 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
330 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
718db961 331 SD_BUS_VTABLE_END
4ad49000 332};
8e2af478 333
a931ad47
LP
334static int bus_cgroup_set_transient_property(
335 Unit *u,
336 CGroupContext *c,
337 const char *name,
338 sd_bus_message *message,
2e59b241 339 UnitWriteFlags flags,
a931ad47
LP
340 sd_bus_error *error) {
341
342 int r;
343
344 assert(u);
345 assert(c);
346 assert(name);
347 assert(message);
348
2e59b241
LP
349 flags |= UNIT_PRIVATE;
350
a931ad47
LP
351 if (streq(name, "Delegate")) {
352 int b;
353
354 r = sd_bus_message_read(message, "b", &b);
355 if (r < 0)
356 return r;
357
2e59b241 358 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
a931ad47 359 c->delegate = b;
02638280
LP
360 c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
361
2e59b241 362 unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
a931ad47
LP
363 }
364
02638280
LP
365 return 1;
366
367 } else if (streq(name, "DelegateControllers")) {
368 CGroupMask mask = 0;
369
370 r = sd_bus_message_enter_container(message, 'a', "s");
371 if (r < 0)
372 return r;
373
374 for (;;) {
375 CGroupController cc;
376 const char *t;
377
378 r = sd_bus_message_read(message, "s", &t);
379 if (r < 0)
380 return r;
381 if (r == 0)
382 break;
383
384 cc = cgroup_controller_from_string(t);
385 if (cc < 0)
e74f76ca 386 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup contoller '%s'", t);
02638280
LP
387
388 mask |= CGROUP_CONTROLLER_TO_MASK(cc);
389 }
390
391 r = sd_bus_message_exit_container(message);
392 if (r < 0)
393 return r;
394
2e59b241 395 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
02638280
LP
396 _cleanup_free_ char *t = NULL;
397
398 r = cg_mask_to_string(mask, &t);
399 if (r < 0)
400 return r;
401
402 c->delegate = true;
1bdfc7b9
YW
403 if (mask == 0)
404 c->delegate_controllers = 0;
405 else
406 c->delegate_controllers |= mask;
02638280 407
2e59b241 408 unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
02638280
LP
409 }
410
a931ad47
LP
411 return 1;
412 }
413
414 return 0;
415}
416
681ae88e
YW
417static int bus_cgroup_set_boolean(
418 Unit *u,
419 const char *name,
420 bool *p,
421 CGroupMask mask,
422 sd_bus_message *message,
423 UnitWriteFlags flags,
424 sd_bus_error *error) {
425
426 int b, r;
427
428 assert(p);
429
430 r = sd_bus_message_read(message, "b", &b);
431 if (r < 0)
432 return r;
433
434 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
435 *p = b;
436 unit_invalidate_cgroup(u, mask);
437 unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
438 }
439
440 return 1;
441}
442
443static BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID,);
444static BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID,);
445static BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID,);
446static BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID,);
447static BUS_DEFINE_SET_CGROUP_WEIGHT(memory, CGROUP_MASK_MEMORY, , CGROUP_LIMIT_MAX, "infinity");
448static BUS_DEFINE_SET_CGROUP_WEIGHT(tasks_max, CGROUP_MASK_PIDS, , (uint64_t) -1, "infinity");
449static BUS_DEFINE_SET_CGROUP_SCALE(memory, CGROUP_MASK_MEMORY, physical_memory_scale);
450static BUS_DEFINE_SET_CGROUP_SCALE(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale);
451
8e2af478
LP
452int bus_cgroup_set_property(
453 Unit *u,
454 CGroupContext *c,
455 const char *name,
718db961 456 sd_bus_message *message,
2e59b241 457 UnitWriteFlags flags,
718db961
LP
458 sd_bus_error *error) {
459
9be57249 460 CGroupIOLimitType iol_type;
718db961 461 int r;
8e2af478 462
8e2af478
LP
463 assert(u);
464 assert(c);
718db961
LP
465 assert(name);
466 assert(message);
8e2af478 467
2e59b241
LP
468 flags |= UNIT_PRIVATE;
469
681ae88e
YW
470 if (streq(name, "CPUAccounting"))
471 return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU, message, flags, error);
8e2af478 472
681ae88e
YW
473 if (streq(name, "CPUWeight"))
474 return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
8e2af478 475
681ae88e
YW
476 if (streq(name, "StartupCPUWeight"))
477 return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
b42defe3 478
681ae88e
YW
479 if (streq(name, "CPUShares"))
480 return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
b42defe3 481
681ae88e
YW
482 if (streq(name, "StartupCPUShares"))
483 return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
66ebf6c0 484
681ae88e
YW
485 if (streq(name, "IOAccounting"))
486 return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
66ebf6c0 487
681ae88e
YW
488 if (streq(name, "IOWeight"))
489 return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
66ebf6c0 490
681ae88e
YW
491 if (streq(name, "StartupIOWeight"))
492 return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
66ebf6c0 493
681ae88e
YW
494 if (streq(name, "BlockIOAccounting"))
495 return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
66ebf6c0 496
681ae88e
YW
497 if (streq(name, "BlockIOWeight"))
498 return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
66ebf6c0 499
681ae88e
YW
500 if (streq(name, "StartupBlockIOWeight"))
501 return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
66ebf6c0 502
681ae88e
YW
503 if (streq(name, "MemoryAccounting"))
504 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
b42defe3 505
681ae88e
YW
506 if (streq(name, "MemoryLow"))
507 return bus_cgroup_set_memory(u, name, &c->memory_low, message, flags, error);
b42defe3 508
681ae88e
YW
509 if (streq(name, "MemoryHigh"))
510 return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
b42defe3 511
681ae88e
YW
512 if (streq(name, "MemorySwapMax"))
513 return bus_cgroup_set_memory(u, name, &c->memory_swap_max, message, flags, error);
95ae05c0 514
681ae88e
YW
515 if (streq(name, "MemoryMax"))
516 return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
d53d9474 517
681ae88e
YW
518 if (streq(name, "MemoryLimit"))
519 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
95ae05c0 520
681ae88e
YW
521 if (streq(name, "MemoryLowScale"))
522 return bus_cgroup_set_memory_scale(u, name, &c->memory_low, message, flags, error);
523
524 if (streq(name, "MemoryHighScale"))
525 return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
526
527 if (streq(name, "MemorySwapMaxScale"))
528 return bus_cgroup_set_memory_scale(u, name, &c->memory_swap_max, message, flags, error);
529
530 if (streq(name, "MemoryMaxScale"))
531 return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
95ae05c0 532
681ae88e
YW
533 if (streq(name, "MemoryLimitScale"))
534 return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
535
60644c3d 536 if (streq(name, "TasksAccounting"))
681ae88e
YW
537 return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error);
538
539 if (streq(name, "TasksMax"))
540 return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error);
541
542 if (streq(name, "TasksMaxScale"))
543 return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error);
544
545 if (streq(name, "CPUQuotaPerSecUSec")) {
b2f8b02e
LP
546 uint64_t u64;
547
548 r = sd_bus_message_read(message, "t", &u64);
549 if (r < 0)
550 return r;
551
552 if (u64 <= 0)
e74f76ca 553 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
b2f8b02e 554
2e59b241 555 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
b2f8b02e 556 c->cpu_quota_per_sec_usec = u64;
e7ab4d1a 557 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
2e59b241 558
d4bf82fc 559 if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
2e59b241 560 unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
d4bf82fc 561 else
2e59b241
LP
562 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
563 * purpose here. */
564 unit_write_settingf(u, flags, "CPUQuota",
565 "CPUQuota=%0.f%%",
566 (double) (c->cpu_quota_per_sec_usec / 10000));
b2f8b02e
LP
567 }
568
569 return 1;
570
9be57249 571 } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
13c31542 572 const char *path;
13c31542
TH
573 unsigned n = 0;
574 uint64_t u64;
575
13c31542
TH
576 r = sd_bus_message_enter_container(message, 'a', "(st)");
577 if (r < 0)
578 return r;
579
580 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
581
32048f54
YW
582 if (!path_startswith(path, "/dev") &&
583 !path_startswith(path, "/run/systemd/inaccessible/"))
d9f7305f
YW
584 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
585
2e59b241 586 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
13c31542
TH
587 CGroupIODeviceLimit *a = NULL, *b;
588
589 LIST_FOREACH(device_limits, b, c->io_device_limits) {
590 if (path_equal(path, b->path)) {
591 a = b;
592 break;
593 }
594 }
595
596 if (!a) {
9be57249
TH
597 CGroupIOLimitType type;
598
13c31542
TH
599 a = new0(CGroupIODeviceLimit, 1);
600 if (!a)
601 return -ENOMEM;
602
603 a->path = strdup(path);
604 if (!a->path) {
605 free(a);
606 return -ENOMEM;
607 }
608
9be57249
TH
609 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
610 a->limits[type] = cgroup_io_limit_defaults[type];
13c31542
TH
611
612 LIST_PREPEND(device_limits, c->io_device_limits, a);
613 }
614
9be57249 615 a->limits[iol_type] = u64;
13c31542
TH
616 }
617
618 n++;
619 }
620 if (r < 0)
621 return r;
622
623 r = sd_bus_message_exit_container(message);
624 if (r < 0)
625 return r;
626
2e59b241 627 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
13c31542
TH
628 CGroupIODeviceLimit *a;
629 _cleanup_free_ char *buf = NULL;
630 _cleanup_fclose_ FILE *f = NULL;
631 size_t size = 0;
632
633 if (n == 0) {
634 LIST_FOREACH(device_limits, a, c->io_device_limits)
9be57249 635 a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
13c31542
TH
636 }
637
638 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
639
640 f = open_memstream(&buf, &size);
641 if (!f)
642 return -ENOMEM;
643
0d536673
LP
644 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
645
9be57249
TH
646 fprintf(f, "%s=\n", name);
647 LIST_FOREACH(device_limits, a, c->io_device_limits)
648 if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
649 fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
13c31542
TH
650
651 r = fflush_and_check(f);
652 if (r < 0)
653 return r;
2e59b241 654 unit_write_setting(u, flags, name, buf);
13c31542
TH
655 }
656
657 return 1;
658
659 } else if (streq(name, "IODeviceWeight")) {
660 const char *path;
661 uint64_t weight;
662 unsigned n = 0;
663
664 r = sd_bus_message_enter_container(message, 'a', "(st)");
665 if (r < 0)
666 return r;
667
668 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
669
32048f54
YW
670 if (!path_startswith(path, "/dev") &&
671 !path_startswith(path, "/run/systemd/inaccessible/"))
d9f7305f
YW
672 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
673
13c31542 674 if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
e74f76ca 675 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
13c31542 676
2e59b241 677 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
13c31542
TH
678 CGroupIODeviceWeight *a = NULL, *b;
679
680 LIST_FOREACH(device_weights, b, c->io_device_weights) {
681 if (path_equal(b->path, path)) {
682 a = b;
683 break;
684 }
685 }
686
687 if (!a) {
688 a = new0(CGroupIODeviceWeight, 1);
689 if (!a)
690 return -ENOMEM;
691
692 a->path = strdup(path);
693 if (!a->path) {
694 free(a);
695 return -ENOMEM;
696 }
fffbc1dc 697 LIST_PREPEND(device_weights, c->io_device_weights, a);
13c31542
TH
698 }
699
700 a->weight = weight;
701 }
702
703 n++;
704 }
705
706 r = sd_bus_message_exit_container(message);
707 if (r < 0)
708 return r;
709
2e59b241 710 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
13c31542
TH
711 _cleanup_free_ char *buf = NULL;
712 _cleanup_fclose_ FILE *f = NULL;
713 CGroupIODeviceWeight *a;
714 size_t size = 0;
715
716 if (n == 0) {
717 while (c->io_device_weights)
718 cgroup_context_free_io_device_weight(c, c->io_device_weights);
719 }
720
721 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
722
723 f = open_memstream(&buf, &size);
724 if (!f)
725 return -ENOMEM;
726
0d536673
LP
727 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
728
729 fputs("IODeviceWeight=\n", f);
13c31542
TH
730 LIST_FOREACH(device_weights, a, c->io_device_weights)
731 fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
732
733 r = fflush_and_check(f);
734 if (r < 0)
735 return r;
2e59b241 736 unit_write_setting(u, flags, name, buf);
13c31542
TH
737 }
738
739 return 1;
740
cd0a7a8e 741 } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
718db961 742 const char *path;
f004c2ca 743 bool read = true;
718db961
LP
744 unsigned n = 0;
745 uint64_t u64;
f004c2ca
G
746
747 if (streq(name, "BlockIOWriteBandwidth"))
748 read = false;
749
718db961
LP
750 r = sd_bus_message_enter_container(message, 'a', "(st)");
751 if (r < 0)
752 return r;
f004c2ca 753
718db961 754 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
f004c2ca 755
32048f54
YW
756 if (!path_startswith(path, "/dev") &&
757 !path_startswith(path, "/run/systemd/inaccessible/"))
d9f7305f
YW
758 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
759
2e59b241 760 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
718db961 761 CGroupBlockIODeviceBandwidth *a = NULL, *b;
f004c2ca
G
762
763 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
979d0311 764 if (path_equal(path, b->path)) {
f004c2ca 765 a = b;
f004c2ca
G
766 break;
767 }
768 }
769
718db961 770 if (!a) {
f004c2ca
G
771 a = new0(CGroupBlockIODeviceBandwidth, 1);
772 if (!a)
773 return -ENOMEM;
774
979d0311
TH
775 a->rbps = CGROUP_LIMIT_MAX;
776 a->wbps = CGROUP_LIMIT_MAX;
f004c2ca
G
777 a->path = strdup(path);
778 if (!a->path) {
779 free(a);
780 return -ENOMEM;
781 }
718db961
LP
782
783 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
f004c2ca
G
784 }
785
979d0311
TH
786 if (read)
787 a->rbps = u64;
788 else
789 a->wbps = u64;
f004c2ca
G
790 }
791
792 n++;
f004c2ca 793 }
718db961
LP
794 if (r < 0)
795 return r;
f004c2ca 796
9c96019d
LP
797 r = sd_bus_message_exit_container(message);
798 if (r < 0)
799 return r;
800
2e59b241 801 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
979d0311 802 CGroupBlockIODeviceBandwidth *a;
f004c2ca
G
803 _cleanup_free_ char *buf = NULL;
804 _cleanup_fclose_ FILE *f = NULL;
f004c2ca
G
805 size_t size = 0;
806
807 if (n == 0) {
979d0311
TH
808 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
809 if (read)
810 a->rbps = CGROUP_LIMIT_MAX;
811 else
812 a->wbps = CGROUP_LIMIT_MAX;
813 }
f004c2ca
G
814 }
815
e7ab4d1a 816 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
3051f187 817
f004c2ca
G
818 f = open_memstream(&buf, &size);
819 if (!f)
820 return -ENOMEM;
821
0d536673
LP
822 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
823
7d6884b6 824 if (read) {
0d536673 825 fputs("BlockIOReadBandwidth=\n", f);
7d6884b6 826 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
979d0311
TH
827 if (a->rbps != CGROUP_LIMIT_MAX)
828 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
f004c2ca 829 } else {
0d536673 830 fputs("BlockIOWriteBandwidth=\n", f);
f004c2ca 831 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
979d0311
TH
832 if (a->wbps != CGROUP_LIMIT_MAX)
833 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
f004c2ca
G
834 }
835
1f2f874c
NC
836 r = fflush_and_check(f);
837 if (r < 0)
838 return r;
2e59b241
LP
839
840 unit_write_setting(u, flags, name, buf);
6f68ecb4
G
841 }
842
843 return 1;
844
845 } else if (streq(name, "BlockIODeviceWeight")) {
718db961 846 const char *path;
d53d9474 847 uint64_t weight;
6f68ecb4
G
848 unsigned n = 0;
849
718db961
LP
850 r = sd_bus_message_enter_container(message, 'a', "(st)");
851 if (r < 0)
852 return r;
6f68ecb4 853
d53d9474 854 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
6f68ecb4 855
32048f54
YW
856 if (!path_startswith(path, "/dev") &&
857 !path_startswith(path, "/run/systemd/inaccessible/"))
d9f7305f
YW
858 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
859
d53d9474 860 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
e74f76ca 861 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
6f68ecb4 862
2e59b241 863 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
718db961 864 CGroupBlockIODeviceWeight *a = NULL, *b;
6f68ecb4
G
865
866 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
867 if (path_equal(b->path, path)) {
868 a = b;
6f68ecb4
G
869 break;
870 }
871 }
872
718db961 873 if (!a) {
6f68ecb4
G
874 a = new0(CGroupBlockIODeviceWeight, 1);
875 if (!a)
876 return -ENOMEM;
877
878 a->path = strdup(path);
879 if (!a->path) {
880 free(a);
881 return -ENOMEM;
882 }
fffbc1dc 883 LIST_PREPEND(device_weights, c->blockio_device_weights, a);
6f68ecb4
G
884 }
885
d53d9474 886 a->weight = weight;
6f68ecb4
G
887 }
888
889 n++;
6f68ecb4
G
890 }
891
9c96019d
LP
892 r = sd_bus_message_exit_container(message);
893 if (r < 0)
894 return r;
895
2e59b241 896 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
6f68ecb4
G
897 _cleanup_free_ char *buf = NULL;
898 _cleanup_fclose_ FILE *f = NULL;
899 CGroupBlockIODeviceWeight *a;
900 size_t size = 0;
901
902 if (n == 0) {
903 while (c->blockio_device_weights)
904 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
905 }
906
e7ab4d1a 907 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
3051f187 908
6f68ecb4
G
909 f = open_memstream(&buf, &size);
910 if (!f)
911 return -ENOMEM;
912
0d536673
LP
913 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
914
915 fputs("BlockIODeviceWeight=\n", f);
6f68ecb4 916 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
d53d9474 917 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
6f68ecb4 918
1f2f874c
NC
919 r = fflush_and_check(f);
920 if (r < 0)
921 return r;
2e59b241
LP
922
923 unit_write_setting(u, flags, name, buf);
f004c2ca
G
924 }
925
926 return 1;
927
7041efe9
LP
928 } else if (streq(name, "DevicePolicy")) {
929 const char *policy;
930 CGroupDevicePolicy p;
931
718db961
LP
932 r = sd_bus_message_read(message, "s", &policy);
933 if (r < 0)
934 return r;
7041efe9 935
7041efe9
LP
936 p = cgroup_device_policy_from_string(policy);
937 if (p < 0)
938 return -EINVAL;
939
2e59b241 940 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7041efe9 941 c->device_policy = p;
e7ab4d1a 942 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
2e59b241 943 unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
7041efe9
LP
944 }
945
946 return 1;
947
948 } else if (streq(name, "DeviceAllow")) {
718db961 949 const char *path, *rwm;
7041efe9
LP
950 unsigned n = 0;
951
718db961
LP
952 r = sd_bus_message_enter_container(message, 'a', "(ss)");
953 if (r < 0)
954 return r;
7041efe9 955
718db961 956 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
7041efe9 957
d9f7305f
YW
958 if ((!is_deviceallow_pattern(path) &&
959 !path_startswith(path, "/run/systemd/inaccessible/")) ||
90060676 960 strpbrk(path, WHITESPACE))
e74f76ca 961 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
7041efe9
LP
962
963 if (isempty(rwm))
964 rwm = "rwm";
965
718db961 966 if (!in_charset(rwm, "rwm"))
e74f76ca 967 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
7041efe9 968
2e59b241 969 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
718db961 970 CGroupDeviceAllow *a = NULL, *b;
ad7bfffd
G
971
972 LIST_FOREACH(device_allow, b, c->device_allow) {
06eb4e3b 973 if (path_equal(b->path, path)) {
ad7bfffd 974 a = b;
ad7bfffd
G
975 break;
976 }
977 }
978
718db961 979 if (!a) {
ad7bfffd
G
980 a = new0(CGroupDeviceAllow, 1);
981 if (!a)
982 return -ENOMEM;
983
984 a->path = strdup(path);
985 if (!a->path) {
986 free(a);
987 return -ENOMEM;
988 }
718db961
LP
989
990 LIST_PREPEND(device_allow, c->device_allow, a);
7041efe9
LP
991 }
992
993 a->r = !!strchr(rwm, 'r');
994 a->w = !!strchr(rwm, 'w');
995 a->m = !!strchr(rwm, 'm');
7041efe9
LP
996 }
997
c2756a68 998 n++;
7041efe9 999 }
43a99a7a
LP
1000 if (r < 0)
1001 return r;
7041efe9 1002
9c96019d
LP
1003 r = sd_bus_message_exit_container(message);
1004 if (r < 0)
1005 return r;
1006
2e59b241 1007 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7041efe9
LP
1008 _cleanup_free_ char *buf = NULL;
1009 _cleanup_fclose_ FILE *f = NULL;
1010 CGroupDeviceAllow *a;
1011 size_t size = 0;
1012
1013 if (n == 0) {
1014 while (c->device_allow)
1015 cgroup_context_free_device_allow(c, c->device_allow);
1016 }
1017
e7ab4d1a 1018 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
3051f187 1019
7041efe9
LP
1020 f = open_memstream(&buf, &size);
1021 if (!f)
1022 return -ENOMEM;
1023
0d536673
LP
1024 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1025
1026 fputs("DeviceAllow=\n", f);
7041efe9
LP
1027 LIST_FOREACH(device_allow, a, c->device_allow)
1028 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1029
1f2f874c
NC
1030 r = fflush_and_check(f);
1031 if (r < 0)
1032 return r;
2e59b241 1033 unit_write_setting(u, flags, name, buf);
7041efe9
LP
1034 }
1035
b42defe3 1036 return 1;
a931ad47 1037
3dc5ca97
LP
1038 } else if (streq(name, "IPAccounting")) {
1039 int b;
1040
1041 r = sd_bus_message_read(message, "b", &b);
1042 if (r < 0)
1043 return r;
1044
2e59b241 1045 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3dc5ca97
LP
1046 c->ip_accounting = b;
1047
1048 unit_invalidate_cgroup_bpf(u);
2e59b241 1049 unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
3dc5ca97
LP
1050 }
1051
1052 return 1;
1053
1054 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1055 IPAddressAccessItem **list;
1056 size_t n = 0;
1057
1058 list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1059
1060 r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1061 if (r < 0)
1062 return r;
1063
1064 for (;;) {
1065 const void *ap;
1066 int32_t family;
1067 uint32_t prefixlen;
1068 size_t an;
1069
1070 r = sd_bus_message_enter_container(message, 'r', "iayu");
1071 if (r < 0)
1072 return r;
1073 if (r == 0)
1074 break;
1075
1076 r = sd_bus_message_read(message, "i", &family);
1077 if (r < 0)
1078 return r;
1079
1080 if (!IN_SET(family, AF_INET, AF_INET6))
e74f76ca 1081 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
3dc5ca97
LP
1082
1083 r = sd_bus_message_read_array(message, 'y', &ap, &an);
1084 if (r < 0)
1085 return r;
1086
1087 if (an != FAMILY_ADDRESS_SIZE(family))
e74f76ca 1088 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
3dc5ca97
LP
1089 af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1090
1091 r = sd_bus_message_read(message, "u", &prefixlen);
1092 if (r < 0)
1093 return r;
1094
1095 if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
e74f76ca 1096 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
3dc5ca97 1097
2e59b241 1098 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3dc5ca97
LP
1099 IPAddressAccessItem *item;
1100
1101 item = new0(IPAddressAccessItem, 1);
1102 if (!item)
1103 return -ENOMEM;
1104
1105 item->family = family;
1106 item->prefixlen = prefixlen;
1107 memcpy(&item->address, ap, an);
1108
1109 LIST_PREPEND(items, *list, item);
1110 }
1111
1112 r = sd_bus_message_exit_container(message);
1113 if (r < 0)
1114 return r;
1115
1116 n++;
1117 }
1118
1119 r = sd_bus_message_exit_container(message);
1120 if (r < 0)
1121 return r;
1122
1274b6c6
LP
1123 *list = ip_address_access_reduce(*list);
1124
2e59b241 1125 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3dc5ca97
LP
1126 _cleanup_free_ char *buf = NULL;
1127 _cleanup_fclose_ FILE *f = NULL;
1128 IPAddressAccessItem *item;
1129 size_t size = 0;
1130
1131 if (n == 0)
1132 *list = ip_address_access_free_all(*list);
1133
1134 unit_invalidate_cgroup_bpf(u);
1135 f = open_memstream(&buf, &size);
1136 if (!f)
1137 return -ENOMEM;
1138
0d536673
LP
1139 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1140
1141 fputs(name, f);
1142 fputs("=\n", f);
3dc5ca97
LP
1143
1144 LIST_FOREACH(items, item, *list) {
1145 char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
1146
1147 errno = 0;
1148 if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
1149 return errno > 0 ? -errno : -EINVAL;
1150
1151 fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
1152 }
1153
1154 r = fflush_and_check(f);
1155 if (r < 0)
1156 return r;
2e59b241
LP
1157
1158 unit_write_setting(u, flags, name, buf);
078ba556
LP
1159
1160 if (*list) {
1161 r = bpf_firewall_supported();
1162 if (r < 0)
1163 return r;
ab8519c2
LP
1164 if (r == 0) {
1165 static bool warned = false;
1166
1167 log_full(warned ? LOG_DEBUG : LOG_WARNING,
1168 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1169 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
1170
1171 warned = true;
1172 }
078ba556 1173 }
3dc5ca97
LP
1174 }
1175
03a7b521 1176 return 1;
a931ad47
LP
1177 }
1178
13ec20d4
YW
1179 if (u->transient && u->load_state == UNIT_STUB)
1180 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
8e2af478
LP
1181
1182 return 0;
1183}