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
);
1102 case SD_BUS_TYPE_BOOLEAN
: {
1106 r
= sd_bus_message_read_basic(m
, type
, &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
, error
, v
, copy_string
);
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
, copy_string
, 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
,
1264 sd_bus_error
*error
,
1265 sd_bus_message
**reply
,
1268 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1272 assert(destination
);
1276 r
= sd_bus_call_method(
1280 "org.freedesktop.DBus.Properties",
1288 r
= bus_message_map_all_properties(m
, map
, !reply
, error
, userdata
);
1293 *reply
= sd_bus_message_ref(m
);
1298 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**ret
) {
1299 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1302 assert(transport
>= 0);
1303 assert(transport
< _BUS_TRANSPORT_MAX
);
1306 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1307 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1309 switch (transport
) {
1311 case BUS_TRANSPORT_LOCAL
:
1313 r
= sd_bus_default_user(&bus
);
1315 r
= sd_bus_default_system(&bus
);
1319 case BUS_TRANSPORT_REMOTE
:
1320 r
= sd_bus_open_system_remote(&bus
, host
);
1323 case BUS_TRANSPORT_MACHINE
:
1324 r
= sd_bus_open_system_machine(&bus
, host
);
1328 assert_not_reached("Hmm, unknown transport type.");
1333 r
= sd_bus_set_exit_on_disconnect(bus
, true);
1343 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1346 assert(transport
>= 0);
1347 assert(transport
< _BUS_TRANSPORT_MAX
);
1350 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1351 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1353 switch (transport
) {
1355 case BUS_TRANSPORT_LOCAL
:
1357 r
= bus_connect_user_systemd(bus
);
1359 r
= bus_connect_system_systemd(bus
);
1363 case BUS_TRANSPORT_REMOTE
:
1364 r
= sd_bus_open_system_remote(bus
, host
);
1367 case BUS_TRANSPORT_MACHINE
:
1368 r
= sd_bus_open_system_machine(bus
, host
);
1372 assert_not_reached("Hmm, unknown transport type.");
1378 int bus_property_get_bool(
1381 const char *interface
,
1382 const char *property
,
1383 sd_bus_message
*reply
,
1385 sd_bus_error
*error
) {
1387 int b
= *(bool*) userdata
;
1389 return sd_bus_message_append_basic(reply
, 'b', &b
);
1392 int bus_property_set_bool(
1395 const char *interface
,
1396 const char *property
,
1397 sd_bus_message
*value
,
1399 sd_bus_error
*error
) {
1403 r
= sd_bus_message_read(value
, "b", &b
);
1407 *(bool *) userdata
= !!b
;
1411 int bus_property_get_id128(
1414 const char *interface
,
1415 const char *property
,
1416 sd_bus_message
*reply
,
1418 sd_bus_error
*error
) {
1420 sd_id128_t
*id
= userdata
;
1422 if (sd_id128_is_null(*id
)) /* Add an empty array if the ID is zero */
1423 return sd_bus_message_append(reply
, "ay", 0);
1425 return sd_bus_message_append_array(reply
, 'y', id
->bytes
, 16);
1428 #if __SIZEOF_SIZE_T__ != 8
1429 int bus_property_get_size(
1432 const char *interface
,
1433 const char *property
,
1434 sd_bus_message
*reply
,
1436 sd_bus_error
*error
) {
1438 uint64_t sz
= *(size_t*) userdata
;
1440 return sd_bus_message_append_basic(reply
, 't', &sz
);
1444 #if __SIZEOF_LONG__ != 8
1445 int bus_property_get_long(
1448 const char *interface
,
1449 const char *property
,
1450 sd_bus_message
*reply
,
1452 sd_bus_error
*error
) {
1454 int64_t l
= *(long*) userdata
;
1456 return sd_bus_message_append_basic(reply
, 'x', &l
);
1459 int bus_property_get_ulong(
1462 const char *interface
,
1463 const char *property
,
1464 sd_bus_message
*reply
,
1466 sd_bus_error
*error
) {
1468 uint64_t ul
= *(unsigned long*) userdata
;
1470 return sd_bus_message_append_basic(reply
, 't', &ul
);
1474 int bus_log_parse_error(int r
) {
1475 return log_error_errno(r
, "Failed to parse bus message: %m");
1478 int bus_log_create_error(int r
) {
1479 return log_error_errno(r
, "Failed to create bus message: %m");
1483 * bus_path_encode_unique() - encode unique object path
1484 * @b: bus connection or NULL
1485 * @prefix: object path prefix
1486 * @sender_id: unique-name of client, or NULL
1487 * @external_id: external ID to be chosen by client, or NULL
1488 * @ret_path: storage for encoded object path pointer
1490 * Whenever we provide a bus API that allows clients to create and manage
1491 * server-side objects, we need to provide a unique name for these objects. If
1492 * we let the server choose the name, we suffer from a race condition: If a
1493 * client creates an object asynchronously, it cannot destroy that object until
1494 * it received the method reply. It cannot know the name of the new object,
1495 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1497 * Therefore, many APIs allow the client to choose the unique name for newly
1498 * created objects. There're two problems to solve, though:
1499 * 1) Object names are usually defined via dbus object paths, which are
1500 * usually globally namespaced. Therefore, multiple clients must be able
1501 * to choose unique object names without interference.
1502 * 2) If multiple libraries share the same bus connection, they must be
1503 * able to choose unique object names without interference.
1504 * The first problem is solved easily by prefixing a name with the
1505 * unique-bus-name of a connection. The server side must enforce this and
1506 * reject any other name. The second problem is solved by providing unique
1507 * suffixes from within sd-bus.
1509 * This helper allows clients to create unique object-paths. It uses the
1510 * template '/prefix/sender_id/external_id' and returns the new path in
1511 * @ret_path (must be freed by the caller).
1512 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1513 * NULL, this function allocates a unique suffix via @b (by requesting a new
1514 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1517 * Returns: 0 on success, negative error code on failure.
1519 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
1520 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
1521 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
1524 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
1525 assert_return(object_path_is_valid(prefix
), -EINVAL
);
1526 assert_return(ret_path
, -EINVAL
);
1529 r
= sd_bus_get_unique_name(b
, &sender_id
);
1535 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
1536 external_id
= external_buf
;
1539 sender_label
= bus_label_escape(sender_id
);
1543 external_label
= bus_label_escape(external_id
);
1544 if (!external_label
)
1547 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
);
1556 * bus_path_decode_unique() - decode unique object path
1557 * @path: object path to decode
1558 * @prefix: object path prefix
1559 * @ret_sender: output parameter for sender-id label
1560 * @ret_external: output parameter for external-id label
1562 * This does the reverse of bus_path_encode_unique() (see its description for
1563 * details). Both trailing labels, sender-id and external-id, are unescaped and
1564 * returned in the given output parameters (the caller must free them).
1566 * Note that this function returns 0 if the path does not match the template
1567 * (see bus_path_encode_unique()), 1 if it matched.
1569 * Returns: Negative error code on failure, 0 if the given object path does not
1570 * match the template (return parameters are set to NULL), 1 if it was
1571 * parsed successfully (return parameters contain allocated labels).
1573 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
1575 char *sender
, *external
;
1577 assert(object_path_is_valid(path
));
1578 assert(object_path_is_valid(prefix
));
1580 assert(ret_external
);
1582 p
= object_path_startswith(path
, prefix
);
1585 *ret_external
= NULL
;
1592 *ret_external
= NULL
;
1596 sender
= bus_label_unescape_n(p
, q
- p
);
1597 external
= bus_label_unescape(q
+ 1);
1598 if (!sender
|| !external
) {
1604 *ret_sender
= sender
;
1605 *ret_external
= external
;
1609 int bus_property_get_rlimit(
1612 const char *interface
,
1613 const char *property
,
1614 sd_bus_message
*reply
,
1616 sd_bus_error
*error
) {
1621 const char *is_soft
;
1627 is_soft
= endswith(property
, "Soft");
1628 rl
= *(struct rlimit
**) userdata
;
1630 x
= is_soft
? rl
->rlim_cur
: rl
->rlim_max
;
1632 struct rlimit buf
= {};
1636 s
= is_soft
? strndupa(property
, is_soft
- property
) : property
;
1638 z
= rlimit_from_string(strstr(s
, "Limit"));
1642 x
= is_soft
? buf
.rlim_cur
: buf
.rlim_max
;
1645 /* rlim_t might have different sizes, let's map
1646 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1648 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
1650 return sd_bus_message_append(reply
, "t", u
);
1653 int bus_track_add_name_many(sd_bus_track
*t
, char **l
) {
1659 /* Continues adding after failure, and returns the first failure. */
1661 STRV_FOREACH(i
, l
) {
1664 k
= sd_bus_track_add_name(t
, *i
);
1665 if (k
< 0 && r
>= 0)
1672 int bus_open_system_watch_bind(sd_bus
**ret
) {
1673 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1679 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1681 r
= sd_bus_new(&bus
);
1685 e
= secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1687 e
= DEFAULT_SYSTEM_BUS_ADDRESS
;
1689 r
= sd_bus_set_address(bus
, e
);
1693 r
= sd_bus_set_bus_client(bus
, true);
1697 r
= sd_bus_set_trusted(bus
, true);
1701 r
= sd_bus_negotiate_creds(bus
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
);
1705 r
= sd_bus_set_watch_bind(bus
, true);
1709 r
= sd_bus_set_connected_signal(bus
, true);
1713 r
= sd_bus_start(bus
);