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 static int name_owner_change_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
59 sd_event
*e
= userdata
;
64 sd_bus_close(sd_bus_message_get_bus(m
));
70 int bus_async_unregister_and_exit(sd_event
*e
, sd_bus
*bus
, const char *name
) {
79 /* We unregister the name here and then wait for the
80 * NameOwnerChanged signal for this event to arrive before we
81 * quit. We do this in order to make sure that any queued
82 * requests are still processed before we really exit. */
84 r
= sd_bus_get_unique_name(bus
, &unique
);
89 "sender='org.freedesktop.DBus',"
91 "interface='org.freedesktop.DBus',"
92 "member='NameOwnerChanged',"
93 "path='/org/freedesktop/DBus',"
95 "arg1='", unique
, "',",
98 r
= sd_bus_add_match_async(bus
, NULL
, match
, name_owner_change_callback
, NULL
, e
);
102 r
= sd_bus_release_name_async(bus
, NULL
, name
, NULL
, NULL
);
109 int bus_event_loop_with_idle(
114 check_idle_t check_idle
,
116 bool exiting
= false;
126 r
= sd_event_get_state(e
);
129 if (r
== SD_EVENT_FINISHED
)
133 idle
= check_idle(userdata
);
137 r
= sd_event_run(e
, exiting
|| !idle
? (uint64_t) -1 : timeout
);
141 if (r
== 0 && !exiting
&& idle
) {
143 r
= sd_bus_try_close(bus
);
147 /* Fallback for dbus1 connections: we
148 * unregister the name and wait for the
149 * response to come through for it */
150 if (r
== -EOPNOTSUPP
) {
152 /* Inform the service manager that we
153 * are going down, so that it will
154 * queue all further start requests,
155 * instead of assuming we are already
157 sd_notify(false, "STOPPING=1");
159 r
= bus_async_unregister_and_exit(e
, bus
, name
);
175 r
= sd_event_get_exit_code(e
, &code
);
182 int bus_name_has_owner(sd_bus
*c
, const char *name
, sd_bus_error
*error
) {
183 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*rep
= NULL
;
184 int r
, has_owner
= 0;
189 r
= sd_bus_call_method(c
,
190 "org.freedesktop.DBus",
191 "/org/freedesktop/dbus",
192 "org.freedesktop.DBus",
201 r
= sd_bus_message_read_basic(rep
, 'b', &has_owner
);
203 return sd_bus_error_set_errno(error
, r
);
208 static int check_good_user(sd_bus_message
*m
, uid_t good_user
) {
209 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
215 if (good_user
== UID_INVALID
)
218 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_EUID
, &creds
);
222 /* Don't trust augmented credentials for authorization */
223 assert_return((sd_bus_creds_get_augmented_mask(creds
) & SD_BUS_CREDS_EUID
) == 0, -EPERM
);
225 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
229 return sender_uid
== good_user
;
233 sd_bus_message
*call
,
236 const char **details
,
246 /* Tests non-interactively! */
248 r
= check_good_user(call
, good_user
);
252 r
= sd_bus_query_sender_privilege(call
, capability
);
259 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*request
= NULL
;
260 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
261 int authorized
= false, challenge
= false;
262 const char *sender
, **k
, **v
;
264 sender
= sd_bus_message_get_sender(call
);
268 r
= sd_bus_message_new_method_call(
271 "org.freedesktop.PolicyKit1",
272 "/org/freedesktop/PolicyKit1/Authority",
273 "org.freedesktop.PolicyKit1.Authority",
274 "CheckAuthorization");
278 r
= sd_bus_message_append(
281 "system-bus-name", 1, "name", "s", sender
,
286 r
= sd_bus_message_open_container(request
, 'a', "{ss}");
290 STRV_FOREACH_PAIR(k
, v
, details
) {
291 r
= sd_bus_message_append(request
, "{ss}", *k
, *v
);
296 r
= sd_bus_message_close_container(request
);
300 r
= sd_bus_message_append(request
, "us", 0, NULL
);
304 r
= sd_bus_call(call
->bus
, request
, 0, e
, &reply
);
306 /* Treat no PK available as access denied */
307 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
)) {
308 sd_bus_error_free(e
);
315 r
= sd_bus_message_enter_container(reply
, 'r', "bba{ss}");
319 r
= sd_bus_message_read(reply
, "bb", &authorized
, &challenge
);
327 *_challenge
= challenge
;
338 typedef struct AsyncPolkitQuery
{
339 sd_bus_message
*request
, *reply
;
340 sd_bus_message_handler_t callback
;
346 static void async_polkit_query_free(AsyncPolkitQuery
*q
) {
351 sd_bus_slot_unref(q
->slot
);
353 if (q
->registry
&& q
->request
)
354 hashmap_remove(q
->registry
, q
->request
);
356 sd_bus_message_unref(q
->request
);
357 sd_bus_message_unref(q
->reply
);
362 static int async_polkit_callback(sd_bus_message
*reply
, void *userdata
, sd_bus_error
*error
) {
363 _cleanup_(sd_bus_error_free
) sd_bus_error error_buffer
= SD_BUS_ERROR_NULL
;
364 AsyncPolkitQuery
*q
= userdata
;
370 q
->slot
= sd_bus_slot_unref(q
->slot
);
371 q
->reply
= sd_bus_message_ref(reply
);
373 r
= sd_bus_message_rewind(q
->request
, true);
375 r
= sd_bus_reply_method_errno(q
->request
, r
, NULL
);
379 r
= q
->callback(q
->request
, q
->userdata
, &error_buffer
);
380 r
= bus_maybe_reply_error(q
->request
, r
, &error_buffer
);
383 async_polkit_query_free(q
);
390 int bus_verify_polkit_async(
391 sd_bus_message
*call
,
394 const char **details
,
398 sd_bus_error
*error
) {
401 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*pk
= NULL
;
403 const char *sender
, **k
, **v
;
404 sd_bus_message_handler_t callback
;
414 r
= check_good_user(call
, good_user
);
419 q
= hashmap_get(*registry
, call
);
421 int authorized
, challenge
;
423 /* This is the second invocation of this function, and
424 * there's already a response from polkit, let's
428 if (sd_bus_message_is_method_error(q
->reply
, NULL
)) {
429 const sd_bus_error
*e
;
431 /* Copy error from polkit reply */
432 e
= sd_bus_message_get_error(q
->reply
);
433 sd_bus_error_copy(error
, e
);
435 /* Treat no PK available as access denied */
436 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
))
439 return -sd_bus_error_get_errno(e
);
442 r
= sd_bus_message_enter_container(q
->reply
, 'r', "bba{ss}");
444 r
= sd_bus_message_read(q
->reply
, "bb", &authorized
, &challenge
);
453 return sd_bus_error_set(error
, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED
, "Interactive authentication required.");
459 r
= sd_bus_query_sender_privilege(call
, capability
);
466 if (sd_bus_get_current_message(call
->bus
) != call
)
469 callback
= sd_bus_get_current_handler(call
->bus
);
473 userdata
= sd_bus_get_current_userdata(call
->bus
);
475 sender
= sd_bus_message_get_sender(call
);
479 c
= sd_bus_message_get_allow_interactive_authorization(call
);
485 r
= hashmap_ensure_allocated(registry
, NULL
);
489 r
= sd_bus_message_new_method_call(
492 "org.freedesktop.PolicyKit1",
493 "/org/freedesktop/PolicyKit1/Authority",
494 "org.freedesktop.PolicyKit1.Authority",
495 "CheckAuthorization");
499 r
= sd_bus_message_append(
502 "system-bus-name", 1, "name", "s", sender
,
507 r
= sd_bus_message_open_container(pk
, 'a', "{ss}");
511 STRV_FOREACH_PAIR(k
, v
, details
) {
512 r
= sd_bus_message_append(pk
, "{ss}", *k
, *v
);
517 r
= sd_bus_message_close_container(pk
);
521 r
= sd_bus_message_append(pk
, "us", !!interactive
, NULL
);
525 q
= new0(AsyncPolkitQuery
, 1);
529 q
->request
= sd_bus_message_ref(call
);
530 q
->callback
= callback
;
531 q
->userdata
= userdata
;
533 r
= hashmap_put(*registry
, call
, q
);
535 async_polkit_query_free(q
);
539 q
->registry
= *registry
;
541 r
= sd_bus_call_async(call
->bus
, &q
->slot
, pk
, async_polkit_callback
, q
, 0);
543 async_polkit_query_free(q
);
553 void bus_verify_polkit_async_registry_free(Hashmap
*registry
) {
555 hashmap_free_with_destructor(registry
, async_polkit_query_free
);
559 int bus_check_peercred(sd_bus
*c
) {
565 fd
= sd_bus_get_fd(c
);
569 r
= getpeercred(fd
, &ucred
);
573 if (ucred
.uid
!= 0 && ucred
.uid
!= geteuid())
579 int bus_connect_system_systemd(sd_bus
**_bus
) {
580 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
586 return sd_bus_default_system(_bus
);
588 /* If we are root then let's talk directly to the system
589 * instance, instead of going via the bus */
591 r
= sd_bus_new(&bus
);
595 r
= sd_bus_set_address(bus
, "unix:path=/run/systemd/private");
599 r
= sd_bus_start(bus
);
601 return sd_bus_default_system(_bus
);
603 r
= bus_check_peercred(bus
);
613 int bus_connect_user_systemd(sd_bus
**_bus
) {
614 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
615 _cleanup_free_
char *ee
= NULL
;
621 e
= secure_getenv("XDG_RUNTIME_DIR");
623 return sd_bus_default_user(_bus
);
625 ee
= bus_address_escape(e
);
629 r
= sd_bus_new(&bus
);
633 bus
->address
= strjoin("unix:path=", ee
, "/systemd/private");
637 r
= sd_bus_start(bus
);
639 return sd_bus_default_user(_bus
);
641 r
= bus_check_peercred(bus
);
651 #define print_property(name, fmt, ...) \
654 printf(fmt "\n", __VA_ARGS__); \
656 printf("%s=" fmt "\n", name, __VA_ARGS__); \
659 int bus_print_property(const char *name
, sd_bus_message
*m
, bool value
, bool all
) {
661 const char *contents
;
667 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
673 case SD_BUS_TYPE_STRING
: {
676 r
= sd_bus_message_read_basic(m
, type
, &s
);
680 if (all
|| !isempty(s
)) {
683 /* This property has a single value, so we need to take
684 * care not to print a new line, everything else is OK. */
685 good
= !strchr(s
, '\n');
686 print_property(name
, "%s", good
? s
: "[unprintable]");
692 case SD_BUS_TYPE_BOOLEAN
: {
695 r
= sd_bus_message_read_basic(m
, type
, &b
);
699 print_property(name
, "%s", yes_no(b
));
704 case SD_BUS_TYPE_UINT64
: {
707 r
= sd_bus_message_read_basic(m
, type
, &u
);
711 /* Yes, heuristics! But we can change this check
712 * should it turn out to not be sufficient */
714 if (endswith(name
, "Timestamp") || STR_IN_SET(name
, "NextElapseUSecRealtime", "LastTriggerUSec")) {
715 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
717 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
719 print_property(name
, "%s", strempty(t
));
721 } else if (strstr(name
, "USec")) {
722 char timespan
[FORMAT_TIMESPAN_MAX
];
724 print_property(name
, "%s", format_timespan(timespan
, sizeof(timespan
), u
, 0));
725 } else if (streq(name
, "RestrictNamespaces")) {
726 _cleanup_free_
char *s
= NULL
;
729 if ((u
& NAMESPACE_FLAGS_ALL
) == 0)
731 else if ((u
& NAMESPACE_FLAGS_ALL
) == NAMESPACE_FLAGS_ALL
)
734 r
= namespace_flag_to_string_many(u
, &s
);
741 print_property(name
, "%s", result
);
743 } else if (streq(name
, "MountFlags")) {
746 result
= mount_propagation_flags_to_string(u
);
750 print_property(name
, "%s", result
);
752 } else if (STR_IN_SET(name
, "CapabilityBoundingSet", "AmbientCapabilities")) {
753 _cleanup_free_
char *s
= NULL
;
755 r
= capability_set_to_string_alloc(u
, &s
);
759 print_property(name
, "%s", s
);
761 } else if ((STR_IN_SET(name
, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u
== CGROUP_WEIGHT_INVALID
) ||
762 (STR_IN_SET(name
, "CPUShares", "StartupCPUShares") && u
== CGROUP_CPU_SHARES_INVALID
) ||
763 (STR_IN_SET(name
, "BlockIOWeight", "StartupBlockIOWeight") && u
== CGROUP_BLKIO_WEIGHT_INVALID
) ||
764 (STR_IN_SET(name
, "MemoryCurrent", "TasksCurrent") && u
== (uint64_t) -1) ||
765 (endswith(name
, "NSec") && u
== (uint64_t) -1))
767 print_property(name
, "%s", "[not set]");
769 else if ((STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u
== CGROUP_LIMIT_MAX
) ||
770 (STR_IN_SET(name
, "TasksMax", "DefaultTasksMax") && u
== (uint64_t) -1) ||
771 (startswith(name
, "Limit") && u
== (uint64_t) -1) ||
772 (startswith(name
, "DefaultLimit") && u
== (uint64_t) -1))
774 print_property(name
, "%s", "infinity");
776 print_property(name
, "%"PRIu64
, u
);
781 case SD_BUS_TYPE_INT64
: {
784 r
= sd_bus_message_read_basic(m
, type
, &i
);
788 print_property(name
, "%"PRIi64
, i
);
793 case SD_BUS_TYPE_UINT32
: {
796 r
= sd_bus_message_read_basic(m
, type
, &u
);
800 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
801 print_property(name
, "%04o", u
);
802 else if (streq(name
, "UID")) {
803 if (u
== UID_INVALID
)
804 print_property(name
, "%s", "[not set]");
806 print_property(name
, "%"PRIu32
, u
);
807 } else if (streq(name
, "GID")) {
808 if (u
== GID_INVALID
)
809 print_property(name
, "%s", "[not set]");
811 print_property(name
, "%"PRIu32
, u
);
813 print_property(name
, "%"PRIu32
, u
);
818 case SD_BUS_TYPE_INT32
: {
821 r
= sd_bus_message_read_basic(m
, type
, &i
);
825 print_property(name
, "%"PRIi32
, i
);
829 case SD_BUS_TYPE_DOUBLE
: {
832 r
= sd_bus_message_read_basic(m
, type
, &d
);
836 print_property(name
, "%g", d
);
840 case SD_BUS_TYPE_ARRAY
:
841 if (streq(contents
, "s")) {
845 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, contents
);
849 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
855 /* This property has multiple space-separated values, so
856 * neither spaces not newlines can be allowed in a value. */
857 good
= str
[strcspn(str
, " \n")] == '\0';
859 printf("%s%s", first
? "" : " ", good
? str
: "[unprintable]");
866 if (first
&& all
&& !value
)
871 r
= sd_bus_message_exit_container(m
);
877 } else if (streq(contents
, "y")) {
881 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
891 for (i
= 0; i
< n
; i
++)
892 printf("%02x", u
[i
]);
899 } else if (streq(contents
, "u")) {
903 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
913 for (i
= 0; i
< n
; i
++)
914 printf("%08x", u
[i
]);
928 int bus_message_print_all_properties(
930 bus_message_print_t func
,
934 Set
**found_properties
) {
940 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
944 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
946 const char *contents
;
948 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &name
);
952 if (found_properties
) {
953 r
= set_ensure_allocated(found_properties
, &string_hash_ops
);
957 r
= set_put(*found_properties
, name
);
958 if (r
< 0 && r
!= EEXIST
)
962 if (!filter
|| strv_find(filter
, name
)) {
963 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
967 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
972 r
= func(name
, m
, value
, all
);
974 r
= bus_print_property(name
, m
, value
, all
);
979 printf("%s=[unprintable]\n", name
);
980 /* skip what we didn't read */
981 r
= sd_bus_message_skip(m
, contents
);
986 r
= sd_bus_message_exit_container(m
);
990 r
= sd_bus_message_skip(m
, "v");
995 r
= sd_bus_message_exit_container(m
);
1002 r
= sd_bus_message_exit_container(m
);
1009 int bus_print_all_properties(
1013 bus_message_print_t func
,
1017 Set
**found_properties
) {
1019 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1020 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1026 r
= sd_bus_call_method(bus
,
1029 "org.freedesktop.DBus.Properties",
1037 return bus_message_print_all_properties(reply
, func
, filter
, value
, all
, found_properties
);
1040 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1041 sd_id128_t
*p
= userdata
;
1046 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
1053 memcpy((*p
).bytes
, v
, n
);
1060 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
, bool copy_string
) {
1064 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
1070 case SD_BUS_TYPE_STRING
: {
1071 const char **p
= userdata
;
1074 r
= sd_bus_message_read_basic(m
, type
, &s
);
1082 return free_and_strdup((char **) userdata
, s
);
1088 case SD_BUS_TYPE_ARRAY
: {
1089 _cleanup_strv_free_
char **l
= NULL
;
1090 char ***p
= userdata
;
1092 r
= bus_message_read_strv_extend(m
, &l
);
1101 case SD_BUS_TYPE_BOOLEAN
: {
1105 r
= sd_bus_message_read_basic(m
, type
, &b
);
1113 case SD_BUS_TYPE_INT32
:
1114 case SD_BUS_TYPE_UINT32
: {
1115 uint32_t u
, *p
= userdata
;
1117 r
= sd_bus_message_read_basic(m
, type
, &u
);
1125 case SD_BUS_TYPE_INT64
:
1126 case SD_BUS_TYPE_UINT64
: {
1127 uint64_t t
, *p
= userdata
;
1129 r
= sd_bus_message_read_basic(m
, type
, &t
);
1137 case SD_BUS_TYPE_DOUBLE
: {
1138 double d
, *p
= userdata
;
1140 r
= sd_bus_message_read_basic(m
, type
, &d
);
1151 int bus_message_map_all_properties(
1153 const struct bus_properties_map
*map
,
1155 sd_bus_error
*error
,
1163 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1167 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1168 const struct bus_properties_map
*prop
;
1170 const char *contents
;
1174 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1178 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1179 if (streq(map
[i
].member
, member
)) {
1185 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1189 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1193 v
= (uint8_t *)userdata
+ prop
->offset
;
1195 r
= prop
->set(sd_bus_message_get_bus(m
), member
, m
, error
, v
);
1197 r
= map_basic(sd_bus_message_get_bus(m
), member
, m
, error
, v
, copy_string
);
1201 r
= sd_bus_message_exit_container(m
);
1205 r
= sd_bus_message_skip(m
, "v");
1210 r
= sd_bus_message_exit_container(m
);
1217 return sd_bus_message_exit_container(m
);
1220 int bus_message_map_properties_changed(
1222 const struct bus_properties_map
*map
,
1224 sd_bus_error
*error
,
1228 int r
, invalidated
, i
;
1233 r
= bus_message_map_all_properties(m
, map
, copy_string
, error
, userdata
);
1237 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1242 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1243 for (i
= 0; map
[i
].member
; i
++)
1244 if (streq(map
[i
].member
, member
)) {
1251 r
= sd_bus_message_exit_container(m
);
1258 int bus_map_all_properties(
1260 const char *destination
,
1262 const struct bus_properties_map
*map
,
1263 sd_bus_error
*error
,
1264 sd_bus_message
**reply
,
1267 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1271 assert(destination
);
1275 r
= sd_bus_call_method(
1279 "org.freedesktop.DBus.Properties",
1287 r
= bus_message_map_all_properties(m
, map
, !reply
, error
, userdata
);
1292 *reply
= sd_bus_message_ref(m
);
1297 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**ret
) {
1298 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1301 assert(transport
>= 0);
1302 assert(transport
< _BUS_TRANSPORT_MAX
);
1305 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1306 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1308 switch (transport
) {
1310 case BUS_TRANSPORT_LOCAL
:
1312 r
= sd_bus_default_user(&bus
);
1314 r
= sd_bus_default_system(&bus
);
1318 case BUS_TRANSPORT_REMOTE
:
1319 r
= sd_bus_open_system_remote(&bus
, host
);
1322 case BUS_TRANSPORT_MACHINE
:
1323 r
= sd_bus_open_system_machine(&bus
, host
);
1327 assert_not_reached("Hmm, unknown transport type.");
1332 r
= sd_bus_set_exit_on_disconnect(bus
, true);
1342 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1345 assert(transport
>= 0);
1346 assert(transport
< _BUS_TRANSPORT_MAX
);
1349 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1350 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1352 switch (transport
) {
1354 case BUS_TRANSPORT_LOCAL
:
1356 r
= bus_connect_user_systemd(bus
);
1358 r
= bus_connect_system_systemd(bus
);
1362 case BUS_TRANSPORT_REMOTE
:
1363 r
= sd_bus_open_system_remote(bus
, host
);
1366 case BUS_TRANSPORT_MACHINE
:
1367 r
= sd_bus_open_system_machine(bus
, host
);
1371 assert_not_reached("Hmm, unknown transport type.");
1377 int bus_property_get_bool(
1380 const char *interface
,
1381 const char *property
,
1382 sd_bus_message
*reply
,
1384 sd_bus_error
*error
) {
1386 int b
= *(bool*) userdata
;
1388 return sd_bus_message_append_basic(reply
, 'b', &b
);
1391 int bus_property_set_bool(
1394 const char *interface
,
1395 const char *property
,
1396 sd_bus_message
*value
,
1398 sd_bus_error
*error
) {
1402 r
= sd_bus_message_read(value
, "b", &b
);
1406 *(bool *) userdata
= !!b
;
1410 int bus_property_get_id128(
1413 const char *interface
,
1414 const char *property
,
1415 sd_bus_message
*reply
,
1417 sd_bus_error
*error
) {
1419 sd_id128_t
*id
= userdata
;
1421 if (sd_id128_is_null(*id
)) /* Add an empty array if the ID is zero */
1422 return sd_bus_message_append(reply
, "ay", 0);
1424 return sd_bus_message_append_array(reply
, 'y', id
->bytes
, 16);
1427 #if __SIZEOF_SIZE_T__ != 8
1428 int bus_property_get_size(
1431 const char *interface
,
1432 const char *property
,
1433 sd_bus_message
*reply
,
1435 sd_bus_error
*error
) {
1437 uint64_t sz
= *(size_t*) userdata
;
1439 return sd_bus_message_append_basic(reply
, 't', &sz
);
1443 #if __SIZEOF_LONG__ != 8
1444 int bus_property_get_long(
1447 const char *interface
,
1448 const char *property
,
1449 sd_bus_message
*reply
,
1451 sd_bus_error
*error
) {
1453 int64_t l
= *(long*) userdata
;
1455 return sd_bus_message_append_basic(reply
, 'x', &l
);
1458 int bus_property_get_ulong(
1461 const char *interface
,
1462 const char *property
,
1463 sd_bus_message
*reply
,
1465 sd_bus_error
*error
) {
1467 uint64_t ul
= *(unsigned long*) userdata
;
1469 return sd_bus_message_append_basic(reply
, 't', &ul
);
1473 int bus_log_parse_error(int r
) {
1474 return log_error_errno(r
, "Failed to parse bus message: %m");
1477 int bus_log_create_error(int r
) {
1478 return log_error_errno(r
, "Failed to create bus message: %m");
1482 * bus_path_encode_unique() - encode unique object path
1483 * @b: bus connection or NULL
1484 * @prefix: object path prefix
1485 * @sender_id: unique-name of client, or NULL
1486 * @external_id: external ID to be chosen by client, or NULL
1487 * @ret_path: storage for encoded object path pointer
1489 * Whenever we provide a bus API that allows clients to create and manage
1490 * server-side objects, we need to provide a unique name for these objects. If
1491 * we let the server choose the name, we suffer from a race condition: If a
1492 * client creates an object asynchronously, it cannot destroy that object until
1493 * it received the method reply. It cannot know the name of the new object,
1494 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1496 * Therefore, many APIs allow the client to choose the unique name for newly
1497 * created objects. There're two problems to solve, though:
1498 * 1) Object names are usually defined via dbus object paths, which are
1499 * usually globally namespaced. Therefore, multiple clients must be able
1500 * to choose unique object names without interference.
1501 * 2) If multiple libraries share the same bus connection, they must be
1502 * able to choose unique object names without interference.
1503 * The first problem is solved easily by prefixing a name with the
1504 * unique-bus-name of a connection. The server side must enforce this and
1505 * reject any other name. The second problem is solved by providing unique
1506 * suffixes from within sd-bus.
1508 * This helper allows clients to create unique object-paths. It uses the
1509 * template '/prefix/sender_id/external_id' and returns the new path in
1510 * @ret_path (must be freed by the caller).
1511 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1512 * NULL, this function allocates a unique suffix via @b (by requesting a new
1513 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1516 * Returns: 0 on success, negative error code on failure.
1518 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
1519 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
1520 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
1523 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
1524 assert_return(object_path_is_valid(prefix
), -EINVAL
);
1525 assert_return(ret_path
, -EINVAL
);
1528 r
= sd_bus_get_unique_name(b
, &sender_id
);
1534 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
1535 external_id
= external_buf
;
1538 sender_label
= bus_label_escape(sender_id
);
1542 external_label
= bus_label_escape(external_id
);
1543 if (!external_label
)
1546 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
);
1555 * bus_path_decode_unique() - decode unique object path
1556 * @path: object path to decode
1557 * @prefix: object path prefix
1558 * @ret_sender: output parameter for sender-id label
1559 * @ret_external: output parameter for external-id label
1561 * This does the reverse of bus_path_encode_unique() (see its description for
1562 * details). Both trailing labels, sender-id and external-id, are unescaped and
1563 * returned in the given output parameters (the caller must free them).
1565 * Note that this function returns 0 if the path does not match the template
1566 * (see bus_path_encode_unique()), 1 if it matched.
1568 * Returns: Negative error code on failure, 0 if the given object path does not
1569 * match the template (return parameters are set to NULL), 1 if it was
1570 * parsed successfully (return parameters contain allocated labels).
1572 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
1574 char *sender
, *external
;
1576 assert(object_path_is_valid(path
));
1577 assert(object_path_is_valid(prefix
));
1579 assert(ret_external
);
1581 p
= object_path_startswith(path
, prefix
);
1584 *ret_external
= NULL
;
1591 *ret_external
= NULL
;
1595 sender
= bus_label_unescape_n(p
, q
- p
);
1596 external
= bus_label_unescape(q
+ 1);
1597 if (!sender
|| !external
) {
1603 *ret_sender
= sender
;
1604 *ret_external
= external
;
1608 int bus_property_get_rlimit(
1611 const char *interface
,
1612 const char *property
,
1613 sd_bus_message
*reply
,
1615 sd_bus_error
*error
) {
1620 const char *is_soft
;
1626 is_soft
= endswith(property
, "Soft");
1627 rl
= *(struct rlimit
**) userdata
;
1629 x
= is_soft
? rl
->rlim_cur
: rl
->rlim_max
;
1631 struct rlimit buf
= {};
1635 s
= is_soft
? strndupa(property
, is_soft
- property
) : property
;
1637 z
= rlimit_from_string(strstr(s
, "Limit"));
1641 x
= is_soft
? buf
.rlim_cur
: buf
.rlim_max
;
1644 /* rlim_t might have different sizes, let's map
1645 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1647 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
1649 return sd_bus_message_append(reply
, "t", u
);
1652 int bus_track_add_name_many(sd_bus_track
*t
, char **l
) {
1658 /* Continues adding after failure, and returns the first failure. */
1660 STRV_FOREACH(i
, l
) {
1663 k
= sd_bus_track_add_name(t
, *i
);
1664 if (k
< 0 && r
>= 0)
1671 int bus_open_system_watch_bind(sd_bus
**ret
) {
1672 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1678 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1680 r
= sd_bus_new(&bus
);
1684 e
= secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1686 e
= DEFAULT_SYSTEM_BUS_ADDRESS
;
1688 r
= sd_bus_set_address(bus
, e
);
1692 r
= sd_bus_set_bus_client(bus
, true);
1696 r
= sd_bus_set_trusted(bus
, true);
1700 r
= sd_bus_negotiate_creds(bus
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
);
1704 r
= sd_bus_set_watch_bind(bus
, true);
1708 r
= sd_bus_set_connected_signal(bus
, true);
1712 r
= sd_bus_start(bus
);