1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/socket.h>
23 #include <sys/capability.h>
29 #include "path-util.h"
34 #include "bus-error.h"
35 #include "bus-message.h"
37 #include "bus-internal.h"
39 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
40 sd_event *e = userdata;
52 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
53 _cleanup_free_ char *match = NULL;
61 /* We unregister the name here and then wait for the
62 * NameOwnerChanged signal for this event to arrive before we
63 * quit. We do this in order to make sure that any queued
64 * requests are still processed before we really exit. */
66 r = sd_bus_get_unique_name(bus, &unique);
71 "sender='org.freedesktop.DBus',"
73 "interface='org.freedesktop.DBus',"
74 "member='NameOwnerChanged',"
75 "path='/org/freedesktop/DBus',"
78 "arg2=''", name, unique);
82 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
86 r = sd_bus_release_name(bus, name);
93 int bus_event_loop_with_idle(
98 check_idle_t check_idle,
100 bool exiting = false;
110 r = sd_event_get_state(e);
113 if (r == SD_EVENT_FINISHED)
117 idle = check_idle(userdata);
121 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
125 if (r == 0 && !exiting) {
127 r = sd_bus_try_close(bus);
132 /* Fallback for dbus1 connections: we
133 * unregister the name and wait for
134 * the response to come through for
137 r = bus_async_unregister_and_exit(e, bus, name);
153 r = sd_event_get_exit_code(e, &code);
160 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
161 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
162 int r, has_owner = 0;
167 r = sd_bus_call_method(c,
168 "org.freedesktop.DBus",
169 "/org/freedesktop/dbus",
170 "org.freedesktop.DBus",
179 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
181 return sd_bus_error_set_errno(error, r);
186 int bus_verify_polkit(
201 r = sd_bus_query_sender_privilege(m, capability);
209 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
210 int authorized = false, challenge = false;
213 sender = sd_bus_message_get_sender(m);
217 r = sd_bus_call_method(
219 "org.freedesktop.PolicyKit1",
220 "/org/freedesktop/PolicyKit1/Authority",
221 "org.freedesktop.PolicyKit1.Authority",
222 "CheckAuthorization",
226 "system-bus-name", 1, "name", "s", sender,
233 /* Treat no PK available as access denied */
234 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
235 sd_bus_error_free(e);
242 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
246 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
254 *_challenge = challenge;
265 typedef struct AsyncPolkitQuery {
266 sd_bus_message *request, *reply;
267 sd_bus_message_handler_t callback;
273 static void async_polkit_query_free(AsyncPolkitQuery *q) {
278 sd_bus_slot_unref(q->slot);
280 if (q->registry && q->request)
281 hashmap_remove(q->registry, q->request);
283 sd_bus_message_unref(q->request);
284 sd_bus_message_unref(q->reply);
289 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
290 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
291 AsyncPolkitQuery *q = userdata;
298 q->slot = sd_bus_slot_unref(q->slot);
299 q->reply = sd_bus_message_ref(reply);
301 r = sd_bus_message_rewind(q->request, true);
303 r = sd_bus_reply_method_errno(q->request, r, NULL);
307 r = q->callback(bus, q->request, q->userdata, &error_buffer);
308 r = bus_maybe_reply_error(q->request, r, &error_buffer);
311 async_polkit_query_free(q);
318 int bus_verify_polkit_async(
326 sd_bus_message_handler_t callback,
330 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
342 q = hashmap_get(*registry, m);
344 int authorized, challenge;
346 /* This is the second invocation of this function, and
347 * there's already a response from polkit, let's
351 if (sd_bus_message_is_method_error(q->reply, NULL)) {
352 const sd_bus_error *e;
354 /* Copy error from polkit reply */
355 e = sd_bus_message_get_error(q->reply);
356 sd_bus_error_copy(error, e);
358 /* Treat no PK available as access denied */
359 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
362 return -sd_bus_error_get_errno(e);
365 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
367 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
379 r = sd_bus_query_sender_privilege(m, capability);
386 sender = sd_bus_message_get_sender(m);
390 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
394 r = sd_bus_message_new_method_call(
397 "org.freedesktop.PolicyKit1",
398 "/org/freedesktop/PolicyKit1/Authority",
399 "org.freedesktop.PolicyKit1.Authority",
400 "CheckAuthorization");
404 r = sd_bus_message_append(
407 "system-bus-name", 1, "name", "s", sender,
415 q = new0(AsyncPolkitQuery, 1);
419 q->request = sd_bus_message_ref(m);
420 q->callback = callback;
421 q->userdata = userdata;
423 r = hashmap_put(*registry, m, q);
425 async_polkit_query_free(q);
429 q->registry = *registry;
431 r = sd_bus_call_async(bus, &q->slot, pk, async_polkit_callback, q, 0);
433 async_polkit_query_free(q);
443 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
447 while ((q = hashmap_steal_first(registry)))
448 async_polkit_query_free(q);
450 hashmap_free(registry);
454 int bus_check_peercred(sd_bus *c) {
461 fd = sd_bus_get_fd(c);
465 l = sizeof(struct ucred);
466 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
469 if (l != sizeof(struct ucred))
472 if (ucred.uid != 0 && ucred.uid != geteuid())
478 int bus_open_system_systemd(sd_bus **_bus) {
479 _cleanup_bus_unref_ sd_bus *bus = NULL;
485 return sd_bus_open_system(_bus);
487 /* If we are root and kdbus is not available, then let's talk
488 * directly to the system instance, instead of going via the
492 r = sd_bus_new(&bus);
496 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
500 bus->bus_client = true;
502 r = sd_bus_start(bus);
509 bus = sd_bus_unref(bus);
512 r = sd_bus_new(&bus);
516 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
520 r = sd_bus_start(bus);
522 return sd_bus_open_system(_bus);
524 r = bus_check_peercred(bus);
534 int bus_open_user_systemd(sd_bus **_bus) {
535 _cleanup_bus_unref_ sd_bus *bus = NULL;
536 _cleanup_free_ char *ee = NULL;
540 /* Try via kdbus first, and then directly */
545 r = sd_bus_new(&bus);
549 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, getuid()) < 0)
552 bus->bus_client = true;
554 r = sd_bus_start(bus);
561 bus = sd_bus_unref(bus);
564 e = secure_getenv("XDG_RUNTIME_DIR");
566 return sd_bus_open_user(_bus);
568 ee = bus_address_escape(e);
572 r = sd_bus_new(&bus);
576 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
580 r = sd_bus_start(bus);
582 return sd_bus_open_user(_bus);
584 r = bus_check_peercred(bus);
594 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
596 const char *contents;
602 r = sd_bus_message_peek_type(property, &type, &contents);
608 case SD_BUS_TYPE_STRING: {
611 r = sd_bus_message_read_basic(property, type, &s);
615 if (all || !isempty(s))
616 printf("%s=%s\n", name, s);
621 case SD_BUS_TYPE_BOOLEAN: {
624 r = sd_bus_message_read_basic(property, type, &b);
628 printf("%s=%s\n", name, yes_no(b));
633 case SD_BUS_TYPE_UINT64: {
636 r = sd_bus_message_read_basic(property, type, &u);
640 /* Yes, heuristics! But we can change this check
641 * should it turn out to not be sufficient */
643 if (endswith(name, "Timestamp")) {
644 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
646 t = format_timestamp(timestamp, sizeof(timestamp), u);
648 printf("%s=%s\n", name, strempty(t));
650 } else if (strstr(name, "USec")) {
651 char timespan[FORMAT_TIMESPAN_MAX];
653 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
655 printf("%s=%llu\n", name, (unsigned long long) u);
660 case SD_BUS_TYPE_UINT32: {
663 r = sd_bus_message_read_basic(property, type, &u);
667 if (strstr(name, "UMask") || strstr(name, "Mode"))
668 printf("%s=%04o\n", name, u);
670 printf("%s=%u\n", name, (unsigned) u);
675 case SD_BUS_TYPE_INT32: {
678 r = sd_bus_message_read_basic(property, type, &i);
682 printf("%s=%i\n", name, (int) i);
686 case SD_BUS_TYPE_DOUBLE: {
689 r = sd_bus_message_read_basic(property, type, &d);
693 printf("%s=%g\n", name, d);
697 case SD_BUS_TYPE_ARRAY:
698 if (streq(contents, "s")) {
702 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
706 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
710 printf("%s%s", first ? "" : " ", str);
722 r = sd_bus_message_exit_container(property);
728 } else if (streq(contents, "y")) {
732 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
741 for (i = 0; i < n; i++)
742 printf("%02x", u[i]);
749 } else if (streq(contents, "u")) {
753 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
762 for (i = 0; i < n; i++)
763 printf("%08x", u[i]);
777 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
778 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
779 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
785 r = sd_bus_call_method(bus,
788 "org.freedesktop.DBus.Properties",
796 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
800 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
802 const char *contents;
804 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
808 if (!filter || strv_find(filter, name)) {
809 r = sd_bus_message_peek_type(reply, NULL, &contents);
813 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
817 r = bus_print_property(name, reply, all);
822 printf("%s=[unprintable]\n", name);
823 /* skip what we didn't read */
824 r = sd_bus_message_skip(reply, contents);
829 r = sd_bus_message_exit_container(reply);
833 r = sd_bus_message_skip(reply, "v");
838 r = sd_bus_message_exit_container(reply);
845 r = sd_bus_message_exit_container(reply);
852 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
853 sd_id128_t *p = userdata;
858 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
865 memcpy((*p).bytes, v, n);
872 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
876 r = sd_bus_message_peek_type(m, &type, NULL);
881 case SD_BUS_TYPE_STRING: {
886 r = sd_bus_message_read_basic(m, type, &s);
904 case SD_BUS_TYPE_ARRAY: {
905 _cleanup_strv_free_ char **l = NULL;
906 char ***p = userdata;
908 r = bus_message_read_strv_extend(m, &l);
919 case SD_BUS_TYPE_BOOLEAN: {
923 r = sd_bus_message_read_basic(m, type, &b);
932 case SD_BUS_TYPE_UINT32: {
934 uint32_t *p = userdata;
936 r = sd_bus_message_read_basic(m, type, &u);
945 case SD_BUS_TYPE_UINT64: {
947 uint64_t *p = userdata;
949 r = sd_bus_message_read_basic(m, type, &t);
965 int bus_map_all_properties(sd_bus *bus,
966 const char *destination,
968 const struct bus_properties_map *map,
970 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
971 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
979 r = sd_bus_call_method(
983 "org.freedesktop.DBus.Properties",
991 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
995 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
996 const struct bus_properties_map *prop;
998 const char *contents;
1002 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1006 for (i = 0, prop = NULL; map[i].member; i++)
1007 if (streq(map[i].member, member)) {
1013 r = sd_bus_message_peek_type(m, NULL, &contents);
1017 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1021 v = (uint8_t *)userdata + prop->offset;
1023 r = prop->set(bus, member, m, &error, v);
1025 r = map_basic(bus, member, m, &error, v);
1029 r = sd_bus_message_exit_container(m);
1033 r = sd_bus_message_skip(m, "v");
1038 r = sd_bus_message_exit_container(m);
1046 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1049 assert(transport >= 0);
1050 assert(transport < _BUS_TRANSPORT_MAX);
1053 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1054 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1056 switch (transport) {
1058 case BUS_TRANSPORT_LOCAL:
1060 r = sd_bus_default_user(bus);
1062 r = sd_bus_default_system(bus);
1066 case BUS_TRANSPORT_REMOTE:
1067 r = sd_bus_open_system_remote(bus, host);
1070 case BUS_TRANSPORT_CONTAINER:
1071 r = sd_bus_open_system_container(bus, host);
1075 assert_not_reached("Hmm, unknown transport type.");
1081 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1084 assert(transport >= 0);
1085 assert(transport < _BUS_TRANSPORT_MAX);
1088 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1089 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1091 switch (transport) {
1093 case BUS_TRANSPORT_LOCAL:
1095 r = bus_open_user_systemd(bus);
1097 r = bus_open_system_systemd(bus);
1101 case BUS_TRANSPORT_REMOTE:
1102 r = sd_bus_open_system_remote(bus, host);
1105 case BUS_TRANSPORT_CONTAINER:
1106 r = sd_bus_open_system_container(bus, host);
1110 assert_not_reached("Hmm, unknown transport type.");
1116 int bus_property_get_bool(
1119 const char *interface,
1120 const char *property,
1121 sd_bus_message *reply,
1123 sd_bus_error *error) {
1125 int b = *(bool*) userdata;
1127 return sd_bus_message_append_basic(reply, 'b', &b);
1130 #if __SIZEOF_SIZE_T__ != 8
1131 int bus_property_get_size(
1134 const char *interface,
1135 const char *property,
1136 sd_bus_message *reply,
1138 sd_bus_error *error) {
1140 uint64_t sz = *(size_t*) userdata;
1142 return sd_bus_message_append_basic(reply, 't', &sz);
1146 #if __SIZEOF_LONG__ != 8
1147 int bus_property_get_long(
1150 const char *interface,
1151 const char *property,
1152 sd_bus_message *reply,
1154 sd_bus_error *error) {
1156 int64_t l = *(long*) userdata;
1158 return sd_bus_message_append_basic(reply, 'x', &l);
1161 int bus_property_get_ulong(
1164 const char *interface,
1165 const char *property,
1166 sd_bus_message *reply,
1168 sd_bus_error *error) {
1170 uint64_t ul = *(unsigned long*) userdata;
1172 return sd_bus_message_append_basic(reply, 't', &ul);
1176 int bus_log_parse_error(int r) {
1177 log_error("Failed to parse bus message: %s", strerror(-r));
1181 int bus_log_create_error(int r) {
1182 log_error("Failed to create bus message: %s", strerror(-r));
1186 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1192 return sd_bus_message_read(
1207 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1211 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1212 sd_bus_reply_method_errno(m, r, error);
1214 } else if (sd_bus_error_is_set(error)) {
1215 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1216 sd_bus_reply_method_error(m, error);
1220 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1221 bus_message_type_to_string(m->header->type),
1224 strna(m->interface),
1226 strna(m->root_container.signature),
1227 bus_error_message(error, r));
1232 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1233 const char *eq, *field;
1239 eq = strchr(assignment, '=');
1241 log_error("Not an assignment: %s", assignment);
1245 field = strndupa(assignment, eq - assignment);
1248 if (streq(field, "CPUQuota")) {
1252 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1254 return bus_log_create_error(r);
1256 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1258 } else if (endswith(eq, "%")) {
1261 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1262 log_error("CPU quota '%s' invalid.", eq);
1266 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1268 return bus_log_create_error(r);
1270 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1272 log_error("CPU quota needs to be in percent.");
1277 return bus_log_create_error(r);
1282 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1284 return bus_log_create_error(r);
1286 if (STR_IN_SET(field,
1287 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1288 "SendSIGHUP", "SendSIGKILL")) {
1290 r = parse_boolean(eq);
1292 log_error("Failed to parse boolean assignment %s.", assignment);
1296 r = sd_bus_message_append(m, "v", "b", r);
1298 } else if (streq(field, "MemoryLimit")) {
1301 r = parse_size(eq, 1024, &bytes);
1303 log_error("Failed to parse bytes specification %s", assignment);
1307 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1309 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1312 r = safe_atou64(eq, &u);
1314 log_error("Failed to parse %s value %s.", field, eq);
1318 r = sd_bus_message_append(m, "v", "t", u);
1320 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1321 r = sd_bus_message_append(m, "v", "s", eq);
1323 else if (streq(field, "DeviceAllow")) {
1326 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1328 const char *path, *rwm, *e;
1330 e = strchr(eq, ' ');
1332 path = strndupa(eq, e - eq);
1339 if (!path_startswith(path, "/dev")) {
1340 log_error("%s is not a device file in /dev.", path);
1344 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1347 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1350 r = sd_bus_message_append(m, "v", "a(st)", 0);
1352 const char *path, *bandwidth, *e;
1355 e = strchr(eq, ' ');
1357 path = strndupa(eq, e - eq);
1360 log_error("Failed to parse %s value %s.", field, eq);
1364 if (!path_startswith(path, "/dev")) {
1365 log_error("%s is not a device file in /dev.", path);
1369 r = parse_size(bandwidth, 1000, &bytes);
1371 log_error("Failed to parse byte value %s.", bandwidth);
1375 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1378 } else if (streq(field, "BlockIODeviceWeight")) {
1381 r = sd_bus_message_append(m, "v", "a(st)", 0);
1383 const char *path, *weight, *e;
1386 e = strchr(eq, ' ');
1388 path = strndupa(eq, e - eq);
1391 log_error("Failed to parse %s value %s.", field, eq);
1395 if (!path_startswith(path, "/dev")) {
1396 log_error("%s is not a device file in /dev.", path);
1400 r = safe_atou64(weight, &u);
1402 log_error("Failed to parse %s value %s.", field, weight);
1405 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1408 } else if (rlimit_from_string(field) >= 0) {
1411 if (streq(eq, "infinity"))
1414 r = safe_atou64(eq, &rl);
1416 log_error("Invalid resource limit: %s", eq);
1421 r = sd_bus_message_append(m, "v", "t", rl);
1423 } else if (streq(field, "Nice")) {
1426 r = safe_atoi32(eq, &i);
1428 log_error("Failed to parse %s value %s.", field, eq);
1432 r = sd_bus_message_append(m, "v", "i", i);
1434 } else if (streq(field, "Environment")) {
1436 r = sd_bus_message_append(m, "v", "as", 1, eq);
1438 } else if (streq(field, "KillSignal")) {
1441 sig = signal_from_string_try_harder(eq);
1443 log_error("Failed to parse %s value %s.", field, eq);
1447 r = sd_bus_message_append(m, "v", "i", sig);
1450 log_error("Unknown assignment %s.", assignment);
1455 return bus_log_create_error(r);