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
, unsigned flags
, sd_bus_error
*error
, void *userdata
) {
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
);
1081 if (flags
& BUS_MAP_STRDUP
)
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
: {
1104 r
= sd_bus_message_read_basic(m
, type
, &b
);
1108 if (flags
& BUS_MAP_BOOLEAN_AS_BOOL
)
1109 * (bool*) userdata
= !!b
;
1111 * (int*) userdata
= b
;
1116 case SD_BUS_TYPE_INT32
:
1117 case SD_BUS_TYPE_UINT32
: {
1118 uint32_t u
, *p
= userdata
;
1120 r
= sd_bus_message_read_basic(m
, type
, &u
);
1128 case SD_BUS_TYPE_INT64
:
1129 case SD_BUS_TYPE_UINT64
: {
1130 uint64_t t
, *p
= userdata
;
1132 r
= sd_bus_message_read_basic(m
, type
, &t
);
1140 case SD_BUS_TYPE_DOUBLE
: {
1141 double d
, *p
= userdata
;
1143 r
= sd_bus_message_read_basic(m
, type
, &d
);
1154 int bus_message_map_all_properties(
1156 const struct bus_properties_map
*map
,
1158 sd_bus_error
*error
,
1166 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1170 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1171 const struct bus_properties_map
*prop
;
1173 const char *contents
;
1177 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1181 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1182 if (streq(map
[i
].member
, member
)) {
1188 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1192 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1196 v
= (uint8_t *)userdata
+ prop
->offset
;
1198 r
= prop
->set(sd_bus_message_get_bus(m
), member
, m
, error
, v
);
1200 r
= map_basic(sd_bus_message_get_bus(m
), member
, m
, flags
, error
, v
);
1204 r
= sd_bus_message_exit_container(m
);
1208 r
= sd_bus_message_skip(m
, "v");
1213 r
= sd_bus_message_exit_container(m
);
1220 return sd_bus_message_exit_container(m
);
1223 int bus_message_map_properties_changed(
1225 const struct bus_properties_map
*map
,
1227 sd_bus_error
*error
,
1231 int r
, invalidated
, i
;
1236 r
= bus_message_map_all_properties(m
, map
, flags
, error
, userdata
);
1240 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1245 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1246 for (i
= 0; map
[i
].member
; i
++)
1247 if (streq(map
[i
].member
, member
)) {
1254 r
= sd_bus_message_exit_container(m
);
1261 int bus_map_all_properties(
1263 const char *destination
,
1265 const struct bus_properties_map
*map
,
1267 sd_bus_error
*error
,
1268 sd_bus_message
**reply
,
1271 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1275 assert(destination
);
1278 assert(reply
|| (flags
& BUS_MAP_STRDUP
));
1280 r
= sd_bus_call_method(
1284 "org.freedesktop.DBus.Properties",
1292 r
= bus_message_map_all_properties(m
, map
, flags
, error
, userdata
);
1297 *reply
= sd_bus_message_ref(m
);
1302 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**ret
) {
1303 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1306 assert(transport
>= 0);
1307 assert(transport
< _BUS_TRANSPORT_MAX
);
1310 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1311 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1313 switch (transport
) {
1315 case BUS_TRANSPORT_LOCAL
:
1317 r
= sd_bus_default_user(&bus
);
1319 r
= sd_bus_default_system(&bus
);
1323 case BUS_TRANSPORT_REMOTE
:
1324 r
= sd_bus_open_system_remote(&bus
, host
);
1327 case BUS_TRANSPORT_MACHINE
:
1328 r
= sd_bus_open_system_machine(&bus
, host
);
1332 assert_not_reached("Hmm, unknown transport type.");
1337 r
= sd_bus_set_exit_on_disconnect(bus
, true);
1347 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1350 assert(transport
>= 0);
1351 assert(transport
< _BUS_TRANSPORT_MAX
);
1354 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1355 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1357 switch (transport
) {
1359 case BUS_TRANSPORT_LOCAL
:
1361 r
= bus_connect_user_systemd(bus
);
1363 r
= bus_connect_system_systemd(bus
);
1367 case BUS_TRANSPORT_REMOTE
:
1368 r
= sd_bus_open_system_remote(bus
, host
);
1371 case BUS_TRANSPORT_MACHINE
:
1372 r
= sd_bus_open_system_machine(bus
, host
);
1376 assert_not_reached("Hmm, unknown transport type.");
1382 int bus_property_get_bool(
1385 const char *interface
,
1386 const char *property
,
1387 sd_bus_message
*reply
,
1389 sd_bus_error
*error
) {
1391 int b
= *(bool*) userdata
;
1393 return sd_bus_message_append_basic(reply
, 'b', &b
);
1396 int bus_property_set_bool(
1399 const char *interface
,
1400 const char *property
,
1401 sd_bus_message
*value
,
1403 sd_bus_error
*error
) {
1407 r
= sd_bus_message_read(value
, "b", &b
);
1411 *(bool *) userdata
= !!b
;
1415 int bus_property_get_id128(
1418 const char *interface
,
1419 const char *property
,
1420 sd_bus_message
*reply
,
1422 sd_bus_error
*error
) {
1424 sd_id128_t
*id
= userdata
;
1426 if (sd_id128_is_null(*id
)) /* Add an empty array if the ID is zero */
1427 return sd_bus_message_append(reply
, "ay", 0);
1429 return sd_bus_message_append_array(reply
, 'y', id
->bytes
, 16);
1432 #if __SIZEOF_SIZE_T__ != 8
1433 int bus_property_get_size(
1436 const char *interface
,
1437 const char *property
,
1438 sd_bus_message
*reply
,
1440 sd_bus_error
*error
) {
1442 uint64_t sz
= *(size_t*) userdata
;
1444 return sd_bus_message_append_basic(reply
, 't', &sz
);
1448 #if __SIZEOF_LONG__ != 8
1449 int bus_property_get_long(
1452 const char *interface
,
1453 const char *property
,
1454 sd_bus_message
*reply
,
1456 sd_bus_error
*error
) {
1458 int64_t l
= *(long*) userdata
;
1460 return sd_bus_message_append_basic(reply
, 'x', &l
);
1463 int bus_property_get_ulong(
1466 const char *interface
,
1467 const char *property
,
1468 sd_bus_message
*reply
,
1470 sd_bus_error
*error
) {
1472 uint64_t ul
= *(unsigned long*) userdata
;
1474 return sd_bus_message_append_basic(reply
, 't', &ul
);
1478 int bus_log_parse_error(int r
) {
1479 return log_error_errno(r
, "Failed to parse bus message: %m");
1482 int bus_log_create_error(int r
) {
1483 return log_error_errno(r
, "Failed to create bus message: %m");
1487 * bus_path_encode_unique() - encode unique object path
1488 * @b: bus connection or NULL
1489 * @prefix: object path prefix
1490 * @sender_id: unique-name of client, or NULL
1491 * @external_id: external ID to be chosen by client, or NULL
1492 * @ret_path: storage for encoded object path pointer
1494 * Whenever we provide a bus API that allows clients to create and manage
1495 * server-side objects, we need to provide a unique name for these objects. If
1496 * we let the server choose the name, we suffer from a race condition: If a
1497 * client creates an object asynchronously, it cannot destroy that object until
1498 * it received the method reply. It cannot know the name of the new object,
1499 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1501 * Therefore, many APIs allow the client to choose the unique name for newly
1502 * created objects. There're two problems to solve, though:
1503 * 1) Object names are usually defined via dbus object paths, which are
1504 * usually globally namespaced. Therefore, multiple clients must be able
1505 * to choose unique object names without interference.
1506 * 2) If multiple libraries share the same bus connection, they must be
1507 * able to choose unique object names without interference.
1508 * The first problem is solved easily by prefixing a name with the
1509 * unique-bus-name of a connection. The server side must enforce this and
1510 * reject any other name. The second problem is solved by providing unique
1511 * suffixes from within sd-bus.
1513 * This helper allows clients to create unique object-paths. It uses the
1514 * template '/prefix/sender_id/external_id' and returns the new path in
1515 * @ret_path (must be freed by the caller).
1516 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1517 * NULL, this function allocates a unique suffix via @b (by requesting a new
1518 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1521 * Returns: 0 on success, negative error code on failure.
1523 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
1524 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
1525 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
1528 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
1529 assert_return(object_path_is_valid(prefix
), -EINVAL
);
1530 assert_return(ret_path
, -EINVAL
);
1533 r
= sd_bus_get_unique_name(b
, &sender_id
);
1539 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
1540 external_id
= external_buf
;
1543 sender_label
= bus_label_escape(sender_id
);
1547 external_label
= bus_label_escape(external_id
);
1548 if (!external_label
)
1551 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
);
1560 * bus_path_decode_unique() - decode unique object path
1561 * @path: object path to decode
1562 * @prefix: object path prefix
1563 * @ret_sender: output parameter for sender-id label
1564 * @ret_external: output parameter for external-id label
1566 * This does the reverse of bus_path_encode_unique() (see its description for
1567 * details). Both trailing labels, sender-id and external-id, are unescaped and
1568 * returned in the given output parameters (the caller must free them).
1570 * Note that this function returns 0 if the path does not match the template
1571 * (see bus_path_encode_unique()), 1 if it matched.
1573 * Returns: Negative error code on failure, 0 if the given object path does not
1574 * match the template (return parameters are set to NULL), 1 if it was
1575 * parsed successfully (return parameters contain allocated labels).
1577 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
1579 char *sender
, *external
;
1581 assert(object_path_is_valid(path
));
1582 assert(object_path_is_valid(prefix
));
1584 assert(ret_external
);
1586 p
= object_path_startswith(path
, prefix
);
1589 *ret_external
= NULL
;
1596 *ret_external
= NULL
;
1600 sender
= bus_label_unescape_n(p
, q
- p
);
1601 external
= bus_label_unescape(q
+ 1);
1602 if (!sender
|| !external
) {
1608 *ret_sender
= sender
;
1609 *ret_external
= external
;
1613 int bus_property_get_rlimit(
1616 const char *interface
,
1617 const char *property
,
1618 sd_bus_message
*reply
,
1620 sd_bus_error
*error
) {
1625 const char *is_soft
;
1631 is_soft
= endswith(property
, "Soft");
1632 rl
= *(struct rlimit
**) userdata
;
1634 x
= is_soft
? rl
->rlim_cur
: rl
->rlim_max
;
1636 struct rlimit buf
= {};
1640 s
= is_soft
? strndupa(property
, is_soft
- property
) : property
;
1642 z
= rlimit_from_string(strstr(s
, "Limit"));
1646 x
= is_soft
? buf
.rlim_cur
: buf
.rlim_max
;
1649 /* rlim_t might have different sizes, let's map
1650 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1652 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
1654 return sd_bus_message_append(reply
, "t", u
);
1657 int bus_track_add_name_many(sd_bus_track
*t
, char **l
) {
1663 /* Continues adding after failure, and returns the first failure. */
1665 STRV_FOREACH(i
, l
) {
1668 k
= sd_bus_track_add_name(t
, *i
);
1669 if (k
< 0 && r
>= 0)
1676 int bus_open_system_watch_bind(sd_bus
**ret
) {
1677 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1683 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1685 r
= sd_bus_new(&bus
);
1689 e
= secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1691 e
= DEFAULT_SYSTEM_BUS_ADDRESS
;
1693 r
= sd_bus_set_address(bus
, e
);
1697 r
= sd_bus_set_bus_client(bus
, true);
1701 r
= sd_bus_set_trusted(bus
, true);
1705 r
= sd_bus_negotiate_creds(bus
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
);
1709 r
= sd_bus_set_watch_bind(bus
, true);
1713 r
= sd_bus_set_connected_signal(bus
, true);
1717 r
= sd_bus_start(bus
);