1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
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.
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.
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/>.
27 #include <sys/ioctl.h>
28 #include <sys/resource.h>
29 #include <sys/socket.h>
32 #include "sd-bus-protocol.h"
34 #include "sd-daemon.h"
38 #include "alloc-util.h"
39 #include "bus-internal.h"
40 #include "bus-label.h"
41 #include "bus-message.h"
44 #include "cgroup-util.h"
49 #include "mount-util.h"
51 #include "parse-util.h"
52 #include "proc-cmdline.h"
53 //#include "rlimit-util.h"
54 #include "stdio-util.h"
56 #include "user-util.h"
58 #if 0 /// UNNEEDED by elogind
59 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
60 sd_event *e = userdata;
65 sd_bus_close(sd_bus_message_get_bus(m));
71 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
80 /* We unregister the name here and then wait for the
81 * NameOwnerChanged signal for this event to arrive before we
82 * quit. We do this in order to make sure that any queued
83 * requests are still processed before we really exit. */
85 r = sd_bus_get_unique_name(bus, &unique);
90 "sender='org.freedesktop.DBus',"
92 "interface='org.freedesktop.DBus',"
93 "member='NameOwnerChanged',"
94 "path='/org/freedesktop/DBus',"
96 "arg1='", unique, "',",
99 r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
103 r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
110 int bus_event_loop_with_idle(
115 check_idle_t check_idle,
117 bool exiting = false;
127 r = sd_event_get_state(e);
130 if (r == SD_EVENT_FINISHED)
134 idle = check_idle(userdata);
138 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
142 if (r == 0 && !exiting && idle) {
144 r = sd_bus_try_close(bus);
148 /* Fallback for dbus1 connections: we
149 * unregister the name and wait for the
150 * response to come through for it */
151 if (r == -EOPNOTSUPP) {
153 /* Inform the service manager that we
154 * are going down, so that it will
155 * queue all further start requests,
156 * instead of assuming we are already
158 sd_notify(false, "STOPPING=1");
160 r = bus_async_unregister_and_exit(e, bus, name);
176 r = sd_event_get_exit_code(e, &code);
184 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
185 _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
186 int r, has_owner = 0;
191 r = sd_bus_call_method(c,
192 "org.freedesktop.DBus",
193 "/org/freedesktop/dbus",
194 "org.freedesktop.DBus",
203 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
205 return sd_bus_error_set_errno(error, r);
210 static int check_good_user(sd_bus_message *m, uid_t good_user) {
211 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
217 if (good_user == UID_INVALID)
220 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
224 /* Don't trust augmented credentials for authorization */
225 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
227 r = sd_bus_creds_get_euid(creds, &sender_uid);
231 return sender_uid == good_user;
235 sd_bus_message *call,
238 const char **details,
248 /* Tests non-interactively! */
250 r = check_good_user(call, good_user);
254 r = sd_bus_query_sender_privilege(call, capability);
261 _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
262 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
263 int authorized = false, challenge = false;
264 const char *sender, **k, **v;
266 sender = sd_bus_message_get_sender(call);
270 r = sd_bus_message_new_method_call(
273 "org.freedesktop.PolicyKit1",
274 "/org/freedesktop/PolicyKit1/Authority",
275 "org.freedesktop.PolicyKit1.Authority",
276 "CheckAuthorization");
280 r = sd_bus_message_append(
283 "system-bus-name", 1, "name", "s", sender,
288 r = sd_bus_message_open_container(request, 'a', "{ss}");
292 STRV_FOREACH_PAIR(k, v, details) {
293 r = sd_bus_message_append(request, "{ss}", *k, *v);
298 r = sd_bus_message_close_container(request);
302 r = sd_bus_message_append(request, "us", 0, NULL);
306 r = sd_bus_call(call->bus, request, 0, e, &reply);
308 /* Treat no PK available as access denied */
309 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
310 sd_bus_error_free(e);
317 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
321 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
329 *_challenge = challenge;
340 typedef struct AsyncPolkitQuery {
341 sd_bus_message *request, *reply;
342 sd_bus_message_handler_t callback;
348 static void async_polkit_query_free(AsyncPolkitQuery *q) {
353 sd_bus_slot_unref(q->slot);
355 if (q->registry && q->request)
356 hashmap_remove(q->registry, q->request);
358 sd_bus_message_unref(q->request);
359 sd_bus_message_unref(q->reply);
364 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
365 _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
366 AsyncPolkitQuery *q = userdata;
372 q->slot = sd_bus_slot_unref(q->slot);
373 q->reply = sd_bus_message_ref(reply);
375 r = sd_bus_message_rewind(q->request, true);
377 r = sd_bus_reply_method_errno(q->request, r, NULL);
381 r = q->callback(q->request, q->userdata, &error_buffer);
382 r = bus_maybe_reply_error(q->request, r, &error_buffer);
385 async_polkit_query_free(q);
392 int bus_verify_polkit_async(
393 sd_bus_message *call,
396 const char **details,
400 sd_bus_error *error) {
403 _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
405 const char *sender, **k, **v;
406 sd_bus_message_handler_t callback;
416 r = check_good_user(call, good_user);
421 q = hashmap_get(*registry, call);
423 int authorized, challenge;
425 /* This is the second invocation of this function, and
426 * there's already a response from polkit, let's
430 if (sd_bus_message_is_method_error(q->reply, NULL)) {
431 const sd_bus_error *e;
433 /* Copy error from polkit reply */
434 e = sd_bus_message_get_error(q->reply);
435 sd_bus_error_copy(error, e);
437 /* Treat no PK available as access denied */
438 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
441 return -sd_bus_error_get_errno(e);
444 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
446 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
455 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
461 r = sd_bus_query_sender_privilege(call, capability);
468 if (sd_bus_get_current_message(call->bus) != call)
471 callback = sd_bus_get_current_handler(call->bus);
475 userdata = sd_bus_get_current_userdata(call->bus);
477 sender = sd_bus_message_get_sender(call);
481 c = sd_bus_message_get_allow_interactive_authorization(call);
487 r = hashmap_ensure_allocated(registry, NULL);
491 r = sd_bus_message_new_method_call(
494 "org.freedesktop.PolicyKit1",
495 "/org/freedesktop/PolicyKit1/Authority",
496 "org.freedesktop.PolicyKit1.Authority",
497 "CheckAuthorization");
501 r = sd_bus_message_append(
504 "system-bus-name", 1, "name", "s", sender,
509 r = sd_bus_message_open_container(pk, 'a', "{ss}");
513 STRV_FOREACH_PAIR(k, v, details) {
514 r = sd_bus_message_append(pk, "{ss}", *k, *v);
519 r = sd_bus_message_close_container(pk);
523 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
527 q = new0(AsyncPolkitQuery, 1);
531 q->request = sd_bus_message_ref(call);
532 q->callback = callback;
533 q->userdata = userdata;
535 r = hashmap_put(*registry, call, q);
537 async_polkit_query_free(q);
541 q->registry = *registry;
543 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
545 async_polkit_query_free(q);
555 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
557 hashmap_free_with_destructor(registry, async_polkit_query_free);
561 #if 0 /// UNNEEDED by elogind
562 int bus_check_peercred(sd_bus *c) {
568 fd = sd_bus_get_fd(c);
572 r = getpeercred(fd, &ucred);
576 if (ucred.uid != 0 && ucred.uid != geteuid())
582 int bus_connect_system_systemd(sd_bus **_bus) {
583 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
589 return sd_bus_default_system(_bus);
591 /* If we are root then let's talk directly to the system
592 * instance, instead of going via the bus */
594 r = sd_bus_new(&bus);
598 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
602 r = sd_bus_start(bus);
604 return sd_bus_default_system(_bus);
606 r = bus_check_peercred(bus);
610 *_bus = TAKE_PTR(bus);
615 int bus_connect_user_systemd(sd_bus **_bus) {
616 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
617 _cleanup_free_ char *ee = NULL;
623 e = secure_getenv("XDG_RUNTIME_DIR");
625 return sd_bus_default_user(_bus);
627 ee = bus_address_escape(e);
631 r = sd_bus_new(&bus);
635 bus->address = strjoin("unix:path=", ee, "/systemd/private");
639 r = sd_bus_start(bus);
641 return sd_bus_default_user(_bus);
643 r = bus_check_peercred(bus);
647 *_bus = TAKE_PTR(bus);
653 #define print_property(name, fmt, ...) \
656 printf(fmt "\n", __VA_ARGS__); \
658 printf("%s=" fmt "\n", name, __VA_ARGS__); \
661 int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) {
663 const char *contents;
669 r = sd_bus_message_peek_type(m, &type, &contents);
675 case SD_BUS_TYPE_STRING: {
678 r = sd_bus_message_read_basic(m, type, &s);
682 if (all || !isempty(s)) {
685 /* This property has a single value, so we need to take
686 * care not to print a new line, everything else is OK. */
687 good = !strchr(s, '\n');
688 print_property(name, "%s", good ? s : "[unprintable]");
694 case SD_BUS_TYPE_BOOLEAN: {
697 r = sd_bus_message_read_basic(m, type, &b);
701 print_property(name, "%s", yes_no(b));
706 case SD_BUS_TYPE_UINT64: {
709 r = sd_bus_message_read_basic(m, type, &u);
713 /* Yes, heuristics! But we can change this check
714 * should it turn out to not be sufficient */
716 if (endswith(name, "Timestamp") || STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec")) {
717 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
719 t = format_timestamp(timestamp, sizeof(timestamp), u);
721 print_property(name, "%s", strempty(t));
723 } else if (strstr(name, "USec")) {
724 char timespan[FORMAT_TIMESPAN_MAX];
726 print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
727 } else if (streq(name, "RestrictNamespaces")) {
728 _cleanup_free_ char *s = NULL;
731 if ((u & NAMESPACE_FLAGS_ALL) == 0)
733 else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
736 r = namespace_flag_to_string_many(u, &s);
743 print_property(name, "%s", result);
745 } else if (streq(name, "MountFlags")) {
748 result = mount_propagation_flags_to_string(u);
752 print_property(name, "%s", result);
754 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
755 _cleanup_free_ char *s = NULL;
757 r = capability_set_to_string_alloc(u, &s);
761 print_property(name, "%s", s);
763 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
764 (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
765 (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
766 (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
767 (endswith(name, "NSec") && u == (uint64_t) -1))
769 print_property(name, "%s", "[not set]");
771 else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
772 (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
773 (startswith(name, "Limit") && u == (uint64_t) -1) ||
774 (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
776 print_property(name, "%s", "infinity");
778 print_property(name, "%"PRIu64, u);
783 case SD_BUS_TYPE_INT64: {
786 r = sd_bus_message_read_basic(m, type, &i);
790 print_property(name, "%"PRIi64, i);
795 case SD_BUS_TYPE_UINT32: {
798 r = sd_bus_message_read_basic(m, type, &u);
802 if (strstr(name, "UMask") || strstr(name, "Mode"))
803 print_property(name, "%04o", u);
804 else if (streq(name, "UID")) {
805 if (u == UID_INVALID)
806 print_property(name, "%s", "[not set]");
808 print_property(name, "%"PRIu32, u);
809 } else if (streq(name, "GID")) {
810 if (u == GID_INVALID)
811 print_property(name, "%s", "[not set]");
813 print_property(name, "%"PRIu32, u);
815 print_property(name, "%"PRIu32, u);
820 case SD_BUS_TYPE_INT32: {
823 r = sd_bus_message_read_basic(m, type, &i);
827 print_property(name, "%"PRIi32, i);
831 case SD_BUS_TYPE_DOUBLE: {
834 r = sd_bus_message_read_basic(m, type, &d);
838 print_property(name, "%g", d);
842 case SD_BUS_TYPE_ARRAY:
843 if (streq(contents, "s")) {
847 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
851 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
857 /* This property has multiple space-separated values, so
858 * neither spaces not newlines can be allowed in a value. */
859 good = str[strcspn(str, " \n")] == '\0';
861 printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
868 if (first && all && !value)
873 r = sd_bus_message_exit_container(m);
879 } else if (streq(contents, "y")) {
883 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
893 for (i = 0; i < n; i++)
894 printf("%02x", u[i]);
901 } else if (streq(contents, "u")) {
905 r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
915 for (i = 0; i < n; i++)
916 printf("%08x", u[i]);
930 int bus_message_print_all_properties(
932 bus_message_print_t func,
936 Set **found_properties) {
942 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
946 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
948 const char *contents;
950 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
954 if (found_properties) {
955 r = set_ensure_allocated(found_properties, &string_hash_ops);
959 r = set_put(*found_properties, name);
960 if (r < 0 && r != EEXIST)
964 if (!filter || strv_find(filter, name)) {
965 r = sd_bus_message_peek_type(m, NULL, &contents);
969 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
974 r = func(name, m, value, all);
976 r = bus_print_property(name, m, value, all);
981 printf("%s=[unprintable]\n", name);
982 /* skip what we didn't read */
983 r = sd_bus_message_skip(m, contents);
988 r = sd_bus_message_exit_container(m);
992 r = sd_bus_message_skip(m, "v");
997 r = sd_bus_message_exit_container(m);
1004 r = sd_bus_message_exit_container(m);
1011 int bus_print_all_properties(
1015 bus_message_print_t func,
1019 Set **found_properties) {
1021 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1022 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1028 r = sd_bus_call_method(bus,
1031 "org.freedesktop.DBus.Properties",
1039 return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
1042 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1043 sd_id128_t *p = userdata;
1048 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1055 memcpy((*p).bytes, v, n);
1062 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
1066 r = sd_bus_message_peek_type(m, &type, NULL);
1072 case SD_BUS_TYPE_STRING: {
1073 const char **p = userdata;
1076 r = sd_bus_message_read_basic(m, type, &s);
1083 if (flags & BUS_MAP_STRDUP)
1084 return free_and_strdup((char **) userdata, s);
1090 case SD_BUS_TYPE_ARRAY: {
1091 _cleanup_strv_free_ char **l = NULL;
1092 char ***p = userdata;
1094 r = bus_message_read_strv_extend(m, &l);
1103 case SD_BUS_TYPE_BOOLEAN: {
1106 r = sd_bus_message_read_basic(m, type, &b);
1110 if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
1111 * (bool*) userdata = !!b;
1113 * (int*) userdata = b;
1118 case SD_BUS_TYPE_INT32:
1119 case SD_BUS_TYPE_UINT32: {
1120 uint32_t u, *p = userdata;
1122 r = sd_bus_message_read_basic(m, type, &u);
1130 case SD_BUS_TYPE_INT64:
1131 case SD_BUS_TYPE_UINT64: {
1132 uint64_t t, *p = userdata;
1134 r = sd_bus_message_read_basic(m, type, &t);
1142 case SD_BUS_TYPE_DOUBLE: {
1143 double d, *p = userdata;
1145 r = sd_bus_message_read_basic(m, type, &d);
1156 int bus_message_map_all_properties(
1158 const struct bus_properties_map *map,
1160 sd_bus_error *error,
1168 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1172 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1173 const struct bus_properties_map *prop;
1175 const char *contents;
1179 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1183 for (i = 0, prop = NULL; map[i].member; i++)
1184 if (streq(map[i].member, member)) {
1190 r = sd_bus_message_peek_type(m, NULL, &contents);
1194 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1198 v = (uint8_t *)userdata + prop->offset;
1200 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
1202 r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
1206 r = sd_bus_message_exit_container(m);
1210 r = sd_bus_message_skip(m, "v");
1215 r = sd_bus_message_exit_container(m);
1222 return sd_bus_message_exit_container(m);
1225 #if 0 /// UNNEEDED by elogind
1226 int bus_message_map_properties_changed(
1228 const struct bus_properties_map *map,
1230 sd_bus_error *error,
1234 int r, invalidated, i;
1239 r = bus_message_map_all_properties(m, map, flags, error, userdata);
1243 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1248 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1249 for (i = 0; map[i].member; i++)
1250 if (streq(map[i].member, member)) {
1257 r = sd_bus_message_exit_container(m);
1265 int bus_map_all_properties(
1267 const char *destination,
1269 const struct bus_properties_map *map,
1271 sd_bus_error *error,
1272 sd_bus_message **reply,
1275 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1279 assert(destination);
1282 assert(reply || (flags & BUS_MAP_STRDUP));
1284 r = sd_bus_call_method(
1288 "org.freedesktop.DBus.Properties",
1296 r = bus_message_map_all_properties(m, map, flags, error, userdata);
1301 *reply = sd_bus_message_ref(m);
1306 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
1307 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1310 assert(transport >= 0);
1311 assert(transport < _BUS_TRANSPORT_MAX);
1314 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1315 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1317 switch (transport) {
1319 case BUS_TRANSPORT_LOCAL:
1320 #if 0 /// elogind does not support a user bus
1322 r = sd_bus_default_user(&bus);
1325 r = sd_bus_default_system(&bus);
1329 case BUS_TRANSPORT_REMOTE:
1330 r = sd_bus_open_system_remote(&bus, host);
1333 case BUS_TRANSPORT_MACHINE:
1334 r = sd_bus_open_system_machine(&bus, host);
1338 assert_not_reached("Hmm, unknown transport type.");
1343 r = sd_bus_set_exit_on_disconnect(bus, true);
1347 *ret = TAKE_PTR(bus);
1352 #if 0 /// UNNEEDED by elogind
1353 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1356 assert(transport >= 0);
1357 assert(transport < _BUS_TRANSPORT_MAX);
1360 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1361 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1363 switch (transport) {
1365 case BUS_TRANSPORT_LOCAL:
1367 r = bus_connect_user_systemd(bus);
1369 r = bus_connect_system_systemd(bus);
1373 case BUS_TRANSPORT_REMOTE:
1374 r = sd_bus_open_system_remote(bus, host);
1377 case BUS_TRANSPORT_MACHINE:
1378 r = sd_bus_open_system_machine(bus, host);
1382 assert_not_reached("Hmm, unknown transport type.");
1389 int bus_property_get_bool(
1392 const char *interface,
1393 const char *property,
1394 sd_bus_message *reply,
1396 sd_bus_error *error) {
1398 int b = *(bool*) userdata;
1400 return sd_bus_message_append_basic(reply, 'b', &b);
1403 int bus_property_set_bool(
1406 const char *interface,
1407 const char *property,
1408 sd_bus_message *value,
1410 sd_bus_error *error) {
1414 r = sd_bus_message_read(value, "b", &b);
1418 *(bool *) userdata = !!b;
1422 #if 0 /// UNNEEDED by elogind
1423 int bus_property_get_id128(
1426 const char *interface,
1427 const char *property,
1428 sd_bus_message *reply,
1430 sd_bus_error *error) {
1432 sd_id128_t *id = userdata;
1434 if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
1435 return sd_bus_message_append(reply, "ay", 0);
1437 return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
1441 #if __SIZEOF_SIZE_T__ != 8
1442 int bus_property_get_size(
1445 const char *interface,
1446 const char *property,
1447 sd_bus_message *reply,
1449 sd_bus_error *error) {
1451 uint64_t sz = *(size_t*) userdata;
1453 return sd_bus_message_append_basic(reply, 't', &sz);
1457 #if __SIZEOF_LONG__ != 8
1458 int bus_property_get_long(
1461 const char *interface,
1462 const char *property,
1463 sd_bus_message *reply,
1465 sd_bus_error *error) {
1467 int64_t l = *(long*) userdata;
1469 return sd_bus_message_append_basic(reply, 'x', &l);
1472 int bus_property_get_ulong(
1475 const char *interface,
1476 const char *property,
1477 sd_bus_message *reply,
1479 sd_bus_error *error) {
1481 uint64_t ul = *(unsigned long*) userdata;
1483 return sd_bus_message_append_basic(reply, 't', &ul);
1487 int bus_log_parse_error(int r) {
1488 return log_error_errno(r, "Failed to parse bus message: %m");
1491 #if 0 /// UNNEEDED by elogind
1492 int bus_log_create_error(int r) {
1493 return log_error_errno(r, "Failed to create bus message: %m");
1497 #if 0 /// UNNEEDED by elogind
1499 * bus_path_encode_unique() - encode unique object path
1500 * @b: bus connection or NULL
1501 * @prefix: object path prefix
1502 * @sender_id: unique-name of client, or NULL
1503 * @external_id: external ID to be chosen by client, or NULL
1504 * @ret_path: storage for encoded object path pointer
1506 * Whenever we provide a bus API that allows clients to create and manage
1507 * server-side objects, we need to provide a unique name for these objects. If
1508 * we let the server choose the name, we suffer from a race condition: If a
1509 * client creates an object asynchronously, it cannot destroy that object until
1510 * it received the method reply. It cannot know the name of the new object,
1511 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1513 * Therefore, many APIs allow the client to choose the unique name for newly
1514 * created objects. There're two problems to solve, though:
1515 * 1) Object names are usually defined via dbus object paths, which are
1516 * usually globally namespaced. Therefore, multiple clients must be able
1517 * to choose unique object names without interference.
1518 * 2) If multiple libraries share the same bus connection, they must be
1519 * able to choose unique object names without interference.
1520 * The first problem is solved easily by prefixing a name with the
1521 * unique-bus-name of a connection. The server side must enforce this and
1522 * reject any other name. The second problem is solved by providing unique
1523 * suffixes from within sd-bus.
1525 * This helper allows clients to create unique object-paths. It uses the
1526 * template '/prefix/sender_id/external_id' and returns the new path in
1527 * @ret_path (must be freed by the caller).
1528 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1529 * NULL, this function allocates a unique suffix via @b (by requesting a new
1530 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1533 * Returns: 0 on success, negative error code on failure.
1535 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1536 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1537 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1540 assert_return(b || (sender_id && external_id), -EINVAL);
1541 assert_return(object_path_is_valid(prefix), -EINVAL);
1542 assert_return(ret_path, -EINVAL);
1545 r = sd_bus_get_unique_name(b, &sender_id);
1551 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1552 external_id = external_buf;
1555 sender_label = bus_label_escape(sender_id);
1559 external_label = bus_label_escape(external_id);
1560 if (!external_label)
1563 p = strjoin(prefix, "/", sender_label, "/", external_label);
1572 * bus_path_decode_unique() - decode unique object path
1573 * @path: object path to decode
1574 * @prefix: object path prefix
1575 * @ret_sender: output parameter for sender-id label
1576 * @ret_external: output parameter for external-id label
1578 * This does the reverse of bus_path_encode_unique() (see its description for
1579 * details). Both trailing labels, sender-id and external-id, are unescaped and
1580 * returned in the given output parameters (the caller must free them).
1582 * Note that this function returns 0 if the path does not match the template
1583 * (see bus_path_encode_unique()), 1 if it matched.
1585 * Returns: Negative error code on failure, 0 if the given object path does not
1586 * match the template (return parameters are set to NULL), 1 if it was
1587 * parsed successfully (return parameters contain allocated labels).
1589 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
1591 char *sender, *external;
1593 assert(object_path_is_valid(path));
1594 assert(object_path_is_valid(prefix));
1596 assert(ret_external);
1598 p = object_path_startswith(path, prefix);
1601 *ret_external = NULL;
1608 *ret_external = NULL;
1612 sender = bus_label_unescape_n(p, q - p);
1613 external = bus_label_unescape(q + 1);
1614 if (!sender || !external) {
1620 *ret_sender = sender;
1621 *ret_external = external;
1626 #if 0 /// UNNEEDED by elogind
1627 int bus_property_get_rlimit(
1630 const char *interface,
1631 const char *property,
1632 sd_bus_message *reply,
1634 sd_bus_error *error) {
1639 const char *is_soft;
1645 is_soft = endswith(property, "Soft");
1646 rl = *(struct rlimit**) userdata;
1648 x = is_soft ? rl->rlim_cur : rl->rlim_max;
1650 struct rlimit buf = {};
1654 s = is_soft ? strndupa(property, is_soft - property) : property;
1656 z = rlimit_from_string(strstr(s, "Limit"));
1660 x = is_soft ? buf.rlim_cur : buf.rlim_max;
1663 /* rlim_t might have different sizes, let's map
1664 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1666 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
1668 return sd_bus_message_append(reply, "t", u);
1671 int bus_track_add_name_many(sd_bus_track *t, char **l) {
1677 /* Continues adding after failure, and returns the first failure. */
1679 STRV_FOREACH(i, l) {
1682 k = sd_bus_track_add_name(t, *i);
1683 if (k < 0 && r >= 0)
1691 int bus_open_system_watch_bind(sd_bus **ret) {
1692 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1698 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1700 r = sd_bus_new(&bus);
1704 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1706 e = DEFAULT_SYSTEM_BUS_ADDRESS;
1708 r = sd_bus_set_address(bus, e);
1712 r = sd_bus_set_bus_client(bus, true);
1716 r = sd_bus_set_trusted(bus, true);
1720 r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
1724 r = sd_bus_set_watch_bind(bus, true);
1728 r = sd_bus_set_connected_signal(bus, true);
1732 r = sd_bus_start(bus);
1736 *ret = TAKE_PTR(bus);