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
);
607 *_bus
= TAKE_PTR(bus
);
612 int bus_connect_user_systemd(sd_bus
**_bus
) {
613 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
614 _cleanup_free_
char *ee
= NULL
;
620 e
= secure_getenv("XDG_RUNTIME_DIR");
622 return sd_bus_default_user(_bus
);
624 ee
= bus_address_escape(e
);
628 r
= sd_bus_new(&bus
);
632 bus
->address
= strjoin("unix:path=", ee
, "/systemd/private");
636 r
= sd_bus_start(bus
);
638 return sd_bus_default_user(_bus
);
640 r
= bus_check_peercred(bus
);
644 *_bus
= TAKE_PTR(bus
);
649 #define print_property(name, fmt, ...) \
652 printf(fmt "\n", __VA_ARGS__); \
654 printf("%s=" fmt "\n", name, __VA_ARGS__); \
657 int bus_print_property(const char *name
, sd_bus_message
*m
, bool value
, bool all
) {
659 const char *contents
;
665 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
671 case SD_BUS_TYPE_STRING
: {
674 r
= sd_bus_message_read_basic(m
, type
, &s
);
678 if (all
|| !isempty(s
)) {
681 /* This property has a single value, so we need to take
682 * care not to print a new line, everything else is OK. */
683 good
= !strchr(s
, '\n');
684 print_property(name
, "%s", good
? s
: "[unprintable]");
690 case SD_BUS_TYPE_BOOLEAN
: {
693 r
= sd_bus_message_read_basic(m
, type
, &b
);
697 print_property(name
, "%s", yes_no(b
));
702 case SD_BUS_TYPE_UINT64
: {
705 r
= sd_bus_message_read_basic(m
, type
, &u
);
709 /* Yes, heuristics! But we can change this check
710 * should it turn out to not be sufficient */
712 if (endswith(name
, "Timestamp") || STR_IN_SET(name
, "NextElapseUSecRealtime", "LastTriggerUSec")) {
713 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
715 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
717 print_property(name
, "%s", strempty(t
));
719 } else if (strstr(name
, "USec")) {
720 char timespan
[FORMAT_TIMESPAN_MAX
];
722 print_property(name
, "%s", format_timespan(timespan
, sizeof(timespan
), u
, 0));
723 } else if (streq(name
, "RestrictNamespaces")) {
724 _cleanup_free_
char *s
= NULL
;
727 if ((u
& NAMESPACE_FLAGS_ALL
) == 0)
729 else if ((u
& NAMESPACE_FLAGS_ALL
) == NAMESPACE_FLAGS_ALL
)
732 r
= namespace_flag_to_string_many(u
, &s
);
739 print_property(name
, "%s", result
);
741 } else if (streq(name
, "MountFlags")) {
744 result
= mount_propagation_flags_to_string(u
);
748 print_property(name
, "%s", result
);
750 } else if (STR_IN_SET(name
, "CapabilityBoundingSet", "AmbientCapabilities")) {
751 _cleanup_free_
char *s
= NULL
;
753 r
= capability_set_to_string_alloc(u
, &s
);
757 print_property(name
, "%s", s
);
759 } else if ((STR_IN_SET(name
, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u
== CGROUP_WEIGHT_INVALID
) ||
760 (STR_IN_SET(name
, "CPUShares", "StartupCPUShares") && u
== CGROUP_CPU_SHARES_INVALID
) ||
761 (STR_IN_SET(name
, "BlockIOWeight", "StartupBlockIOWeight") && u
== CGROUP_BLKIO_WEIGHT_INVALID
) ||
762 (STR_IN_SET(name
, "MemoryCurrent", "TasksCurrent") && u
== (uint64_t) -1) ||
763 (endswith(name
, "NSec") && u
== (uint64_t) -1))
765 print_property(name
, "%s", "[not set]");
767 else if ((STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u
== CGROUP_LIMIT_MAX
) ||
768 (STR_IN_SET(name
, "TasksMax", "DefaultTasksMax") && u
== (uint64_t) -1) ||
769 (startswith(name
, "Limit") && u
== (uint64_t) -1) ||
770 (startswith(name
, "DefaultLimit") && u
== (uint64_t) -1))
772 print_property(name
, "%s", "infinity");
774 print_property(name
, "%"PRIu64
, u
);
779 case SD_BUS_TYPE_INT64
: {
782 r
= sd_bus_message_read_basic(m
, type
, &i
);
786 print_property(name
, "%"PRIi64
, i
);
791 case SD_BUS_TYPE_UINT32
: {
794 r
= sd_bus_message_read_basic(m
, type
, &u
);
798 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
799 print_property(name
, "%04o", u
);
800 else if (streq(name
, "UID")) {
801 if (u
== UID_INVALID
)
802 print_property(name
, "%s", "[not set]");
804 print_property(name
, "%"PRIu32
, u
);
805 } else if (streq(name
, "GID")) {
806 if (u
== GID_INVALID
)
807 print_property(name
, "%s", "[not set]");
809 print_property(name
, "%"PRIu32
, u
);
811 print_property(name
, "%"PRIu32
, u
);
816 case SD_BUS_TYPE_INT32
: {
819 r
= sd_bus_message_read_basic(m
, type
, &i
);
823 print_property(name
, "%"PRIi32
, i
);
827 case SD_BUS_TYPE_DOUBLE
: {
830 r
= sd_bus_message_read_basic(m
, type
, &d
);
834 print_property(name
, "%g", d
);
838 case SD_BUS_TYPE_ARRAY
:
839 if (streq(contents
, "s")) {
843 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, contents
);
847 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
853 /* This property has multiple space-separated values, so
854 * neither spaces not newlines can be allowed in a value. */
855 good
= str
[strcspn(str
, " \n")] == '\0';
857 printf("%s%s", first
? "" : " ", good
? str
: "[unprintable]");
864 if (first
&& all
&& !value
)
869 r
= sd_bus_message_exit_container(m
);
875 } else if (streq(contents
, "y")) {
879 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
889 for (i
= 0; i
< n
; i
++)
890 printf("%02x", u
[i
]);
897 } else if (streq(contents
, "u")) {
901 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
911 for (i
= 0; i
< n
; i
++)
912 printf("%08x", u
[i
]);
926 int bus_message_print_all_properties(
928 bus_message_print_t func
,
932 Set
**found_properties
) {
938 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
942 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
944 const char *contents
;
946 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &name
);
950 if (found_properties
) {
951 r
= set_ensure_allocated(found_properties
, &string_hash_ops
);
955 r
= set_put(*found_properties
, name
);
956 if (r
< 0 && r
!= EEXIST
)
960 if (!filter
|| strv_find(filter
, name
)) {
961 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
965 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
970 r
= func(name
, m
, value
, all
);
972 r
= bus_print_property(name
, m
, value
, all
);
977 printf("%s=[unprintable]\n", name
);
978 /* skip what we didn't read */
979 r
= sd_bus_message_skip(m
, contents
);
984 r
= sd_bus_message_exit_container(m
);
988 r
= sd_bus_message_skip(m
, "v");
993 r
= sd_bus_message_exit_container(m
);
1000 r
= sd_bus_message_exit_container(m
);
1007 int bus_print_all_properties(
1011 bus_message_print_t func
,
1015 Set
**found_properties
) {
1017 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1018 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1024 r
= sd_bus_call_method(bus
,
1027 "org.freedesktop.DBus.Properties",
1035 return bus_message_print_all_properties(reply
, func
, filter
, value
, all
, found_properties
);
1038 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1039 sd_id128_t
*p
= userdata
;
1044 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
1051 memcpy((*p
).bytes
, v
, n
);
1058 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, unsigned flags
, sd_bus_error
*error
, void *userdata
) {
1062 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
1068 case SD_BUS_TYPE_STRING
: {
1069 const char **p
= userdata
;
1072 r
= sd_bus_message_read_basic(m
, type
, &s
);
1079 if (flags
& BUS_MAP_STRDUP
)
1080 return free_and_strdup((char **) userdata
, s
);
1086 case SD_BUS_TYPE_ARRAY
: {
1087 _cleanup_strv_free_
char **l
= NULL
;
1088 char ***p
= userdata
;
1090 r
= bus_message_read_strv_extend(m
, &l
);
1099 case SD_BUS_TYPE_BOOLEAN
: {
1102 r
= sd_bus_message_read_basic(m
, type
, &b
);
1106 if (flags
& BUS_MAP_BOOLEAN_AS_BOOL
)
1107 * (bool*) userdata
= !!b
;
1109 * (int*) userdata
= b
;
1114 case SD_BUS_TYPE_INT32
:
1115 case SD_BUS_TYPE_UINT32
: {
1116 uint32_t u
, *p
= userdata
;
1118 r
= sd_bus_message_read_basic(m
, type
, &u
);
1126 case SD_BUS_TYPE_INT64
:
1127 case SD_BUS_TYPE_UINT64
: {
1128 uint64_t t
, *p
= userdata
;
1130 r
= sd_bus_message_read_basic(m
, type
, &t
);
1138 case SD_BUS_TYPE_DOUBLE
: {
1139 double d
, *p
= userdata
;
1141 r
= sd_bus_message_read_basic(m
, type
, &d
);
1152 int bus_message_map_all_properties(
1154 const struct bus_properties_map
*map
,
1156 sd_bus_error
*error
,
1164 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1168 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1169 const struct bus_properties_map
*prop
;
1171 const char *contents
;
1175 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1179 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1180 if (streq(map
[i
].member
, member
)) {
1186 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1190 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1194 v
= (uint8_t *)userdata
+ prop
->offset
;
1196 r
= prop
->set(sd_bus_message_get_bus(m
), member
, m
, error
, v
);
1198 r
= map_basic(sd_bus_message_get_bus(m
), member
, m
, flags
, error
, v
);
1202 r
= sd_bus_message_exit_container(m
);
1206 r
= sd_bus_message_skip(m
, "v");
1211 r
= sd_bus_message_exit_container(m
);
1218 return sd_bus_message_exit_container(m
);
1221 int bus_message_map_properties_changed(
1223 const struct bus_properties_map
*map
,
1225 sd_bus_error
*error
,
1229 int r
, invalidated
, i
;
1234 r
= bus_message_map_all_properties(m
, map
, flags
, error
, userdata
);
1238 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1243 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1244 for (i
= 0; map
[i
].member
; i
++)
1245 if (streq(map
[i
].member
, member
)) {
1252 r
= sd_bus_message_exit_container(m
);
1259 int bus_map_all_properties(
1261 const char *destination
,
1263 const struct bus_properties_map
*map
,
1265 sd_bus_error
*error
,
1266 sd_bus_message
**reply
,
1269 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1273 assert(destination
);
1276 assert(reply
|| (flags
& BUS_MAP_STRDUP
));
1278 r
= sd_bus_call_method(
1282 "org.freedesktop.DBus.Properties",
1290 r
= bus_message_map_all_properties(m
, map
, flags
, error
, userdata
);
1295 *reply
= sd_bus_message_ref(m
);
1300 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**ret
) {
1301 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1304 assert(transport
>= 0);
1305 assert(transport
< _BUS_TRANSPORT_MAX
);
1308 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1309 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1311 switch (transport
) {
1313 case BUS_TRANSPORT_LOCAL
:
1315 r
= sd_bus_default_user(&bus
);
1317 r
= sd_bus_default_system(&bus
);
1321 case BUS_TRANSPORT_REMOTE
:
1322 r
= sd_bus_open_system_remote(&bus
, host
);
1325 case BUS_TRANSPORT_MACHINE
:
1326 r
= sd_bus_open_system_machine(&bus
, host
);
1330 assert_not_reached("Hmm, unknown transport type.");
1335 r
= sd_bus_set_exit_on_disconnect(bus
, true);
1339 *ret
= TAKE_PTR(bus
);
1344 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1347 assert(transport
>= 0);
1348 assert(transport
< _BUS_TRANSPORT_MAX
);
1351 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1352 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1354 switch (transport
) {
1356 case BUS_TRANSPORT_LOCAL
:
1358 r
= bus_connect_user_systemd(bus
);
1360 r
= bus_connect_system_systemd(bus
);
1364 case BUS_TRANSPORT_REMOTE
:
1365 r
= sd_bus_open_system_remote(bus
, host
);
1368 case BUS_TRANSPORT_MACHINE
:
1369 r
= sd_bus_open_system_machine(bus
, host
);
1373 assert_not_reached("Hmm, unknown transport type.");
1379 int bus_property_get_bool(
1382 const char *interface
,
1383 const char *property
,
1384 sd_bus_message
*reply
,
1386 sd_bus_error
*error
) {
1388 int b
= *(bool*) userdata
;
1390 return sd_bus_message_append_basic(reply
, 'b', &b
);
1393 int bus_property_set_bool(
1396 const char *interface
,
1397 const char *property
,
1398 sd_bus_message
*value
,
1400 sd_bus_error
*error
) {
1404 r
= sd_bus_message_read(value
, "b", &b
);
1408 *(bool *) userdata
= !!b
;
1412 int bus_property_get_id128(
1415 const char *interface
,
1416 const char *property
,
1417 sd_bus_message
*reply
,
1419 sd_bus_error
*error
) {
1421 sd_id128_t
*id
= userdata
;
1423 if (sd_id128_is_null(*id
)) /* Add an empty array if the ID is zero */
1424 return sd_bus_message_append(reply
, "ay", 0);
1426 return sd_bus_message_append_array(reply
, 'y', id
->bytes
, 16);
1429 #if __SIZEOF_SIZE_T__ != 8
1430 int bus_property_get_size(
1433 const char *interface
,
1434 const char *property
,
1435 sd_bus_message
*reply
,
1437 sd_bus_error
*error
) {
1439 uint64_t sz
= *(size_t*) userdata
;
1441 return sd_bus_message_append_basic(reply
, 't', &sz
);
1445 #if __SIZEOF_LONG__ != 8
1446 int bus_property_get_long(
1449 const char *interface
,
1450 const char *property
,
1451 sd_bus_message
*reply
,
1453 sd_bus_error
*error
) {
1455 int64_t l
= *(long*) userdata
;
1457 return sd_bus_message_append_basic(reply
, 'x', &l
);
1460 int bus_property_get_ulong(
1463 const char *interface
,
1464 const char *property
,
1465 sd_bus_message
*reply
,
1467 sd_bus_error
*error
) {
1469 uint64_t ul
= *(unsigned long*) userdata
;
1471 return sd_bus_message_append_basic(reply
, 't', &ul
);
1475 int bus_log_parse_error(int r
) {
1476 return log_error_errno(r
, "Failed to parse bus message: %m");
1479 int bus_log_create_error(int r
) {
1480 return log_error_errno(r
, "Failed to create bus message: %m");
1484 * bus_path_encode_unique() - encode unique object path
1485 * @b: bus connection or NULL
1486 * @prefix: object path prefix
1487 * @sender_id: unique-name of client, or NULL
1488 * @external_id: external ID to be chosen by client, or NULL
1489 * @ret_path: storage for encoded object path pointer
1491 * Whenever we provide a bus API that allows clients to create and manage
1492 * server-side objects, we need to provide a unique name for these objects. If
1493 * we let the server choose the name, we suffer from a race condition: If a
1494 * client creates an object asynchronously, it cannot destroy that object until
1495 * it received the method reply. It cannot know the name of the new object,
1496 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1498 * Therefore, many APIs allow the client to choose the unique name for newly
1499 * created objects. There're two problems to solve, though:
1500 * 1) Object names are usually defined via dbus object paths, which are
1501 * usually globally namespaced. Therefore, multiple clients must be able
1502 * to choose unique object names without interference.
1503 * 2) If multiple libraries share the same bus connection, they must be
1504 * able to choose unique object names without interference.
1505 * The first problem is solved easily by prefixing a name with the
1506 * unique-bus-name of a connection. The server side must enforce this and
1507 * reject any other name. The second problem is solved by providing unique
1508 * suffixes from within sd-bus.
1510 * This helper allows clients to create unique object-paths. It uses the
1511 * template '/prefix/sender_id/external_id' and returns the new path in
1512 * @ret_path (must be freed by the caller).
1513 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1514 * NULL, this function allocates a unique suffix via @b (by requesting a new
1515 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1518 * Returns: 0 on success, negative error code on failure.
1520 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
1521 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
1522 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
1525 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
1526 assert_return(object_path_is_valid(prefix
), -EINVAL
);
1527 assert_return(ret_path
, -EINVAL
);
1530 r
= sd_bus_get_unique_name(b
, &sender_id
);
1536 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
1537 external_id
= external_buf
;
1540 sender_label
= bus_label_escape(sender_id
);
1544 external_label
= bus_label_escape(external_id
);
1545 if (!external_label
)
1548 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
);
1557 * bus_path_decode_unique() - decode unique object path
1558 * @path: object path to decode
1559 * @prefix: object path prefix
1560 * @ret_sender: output parameter for sender-id label
1561 * @ret_external: output parameter for external-id label
1563 * This does the reverse of bus_path_encode_unique() (see its description for
1564 * details). Both trailing labels, sender-id and external-id, are unescaped and
1565 * returned in the given output parameters (the caller must free them).
1567 * Note that this function returns 0 if the path does not match the template
1568 * (see bus_path_encode_unique()), 1 if it matched.
1570 * Returns: Negative error code on failure, 0 if the given object path does not
1571 * match the template (return parameters are set to NULL), 1 if it was
1572 * parsed successfully (return parameters contain allocated labels).
1574 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
1576 char *sender
, *external
;
1578 assert(object_path_is_valid(path
));
1579 assert(object_path_is_valid(prefix
));
1581 assert(ret_external
);
1583 p
= object_path_startswith(path
, prefix
);
1586 *ret_external
= NULL
;
1593 *ret_external
= NULL
;
1597 sender
= bus_label_unescape_n(p
, q
- p
);
1598 external
= bus_label_unescape(q
+ 1);
1599 if (!sender
|| !external
) {
1605 *ret_sender
= sender
;
1606 *ret_external
= external
;
1610 int bus_property_get_rlimit(
1613 const char *interface
,
1614 const char *property
,
1615 sd_bus_message
*reply
,
1617 sd_bus_error
*error
) {
1622 const char *is_soft
;
1628 is_soft
= endswith(property
, "Soft");
1629 rl
= *(struct rlimit
**) userdata
;
1631 x
= is_soft
? rl
->rlim_cur
: rl
->rlim_max
;
1633 struct rlimit buf
= {};
1637 s
= is_soft
? strndupa(property
, is_soft
- property
) : property
;
1639 z
= rlimit_from_string(strstr(s
, "Limit"));
1643 x
= is_soft
? buf
.rlim_cur
: buf
.rlim_max
;
1646 /* rlim_t might have different sizes, let's map
1647 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1649 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
1651 return sd_bus_message_append(reply
, "t", u
);
1654 int bus_track_add_name_many(sd_bus_track
*t
, char **l
) {
1660 /* Continues adding after failure, and returns the first failure. */
1662 STRV_FOREACH(i
, l
) {
1665 k
= sd_bus_track_add_name(t
, *i
);
1666 if (k
< 0 && r
>= 0)
1673 int bus_open_system_watch_bind(sd_bus
**ret
) {
1674 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1680 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1682 r
= sd_bus_new(&bus
);
1686 e
= secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1688 e
= DEFAULT_SYSTEM_BUS_ADDRESS
;
1690 r
= sd_bus_set_address(bus
, e
);
1694 r
= sd_bus_set_bus_client(bus
, true);
1698 r
= sd_bus_set_trusted(bus
, true);
1702 r
= sd_bus_negotiate_creds(bus
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
);
1706 r
= sd_bus_set_watch_bind(bus
, true);
1710 r
= sd_bus_set_connected_signal(bus
, true);
1714 r
= sd_bus_start(bus
);
1718 *ret
= TAKE_PTR(bus
);