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
*property
, bool value
, bool all
) {
661 const char *contents
;
667 r
= sd_bus_message_peek_type(property
, &type
, &contents
);
673 case SD_BUS_TYPE_STRING
: {
676 r
= sd_bus_message_read_basic(property
, 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(property
, type
, &b
);
699 print_property(name
, "%s", yes_no(b
));
704 case SD_BUS_TYPE_UINT64
: {
707 r
= sd_bus_message_read_basic(property
, 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(property
, type
, &i
);
788 print_property(name
, "%"PRIi64
, i
);
793 case SD_BUS_TYPE_UINT32
: {
796 r
= sd_bus_message_read_basic(property
, 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(property
, type
, &i
);
825 print_property(name
, "%"PRIi32
, i
);
829 case SD_BUS_TYPE_DOUBLE
: {
832 r
= sd_bus_message_read_basic(property
, 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(property
, SD_BUS_TYPE_ARRAY
, contents
);
849 while ((r
= sd_bus_message_read_basic(property
, 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(property
);
877 } else if (streq(contents
, "y")) {
881 r
= sd_bus_message_read_array(property
, 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(property
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
913 for (i
= 0; i
< n
; i
++)
914 printf("%08x", u
[i
]);
928 int bus_print_all_properties(sd_bus
*bus
, const char *dest
, const char *path
, char **filter
, bool value
, bool all
) {
929 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
930 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
936 r
= sd_bus_call_method(bus
,
939 "org.freedesktop.DBus.Properties",
947 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
951 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
953 const char *contents
;
955 r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &name
);
959 if (!filter
|| strv_find(filter
, name
)) {
960 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
964 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
968 r
= bus_print_property(name
, reply
, value
, all
);
973 printf("%s=[unprintable]\n", name
);
974 /* skip what we didn't read */
975 r
= sd_bus_message_skip(reply
, contents
);
980 r
= sd_bus_message_exit_container(reply
);
984 r
= sd_bus_message_skip(reply
, "v");
989 r
= sd_bus_message_exit_container(reply
);
996 r
= sd_bus_message_exit_container(reply
);
1003 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1004 sd_id128_t
*p
= userdata
;
1009 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
1016 memcpy((*p
).bytes
, v
, n
);
1023 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1027 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
1033 case SD_BUS_TYPE_STRING
: {
1034 char **p
= userdata
;
1037 r
= sd_bus_message_read_basic(m
, type
, &s
);
1044 return free_and_strdup(p
, s
);
1047 case SD_BUS_TYPE_ARRAY
: {
1048 _cleanup_strv_free_
char **l
= NULL
;
1049 char ***p
= userdata
;
1051 r
= bus_message_read_strv_extend(m
, &l
);
1061 case SD_BUS_TYPE_BOOLEAN
: {
1065 r
= sd_bus_message_read_basic(m
, type
, &b
);
1073 case SD_BUS_TYPE_INT32
:
1074 case SD_BUS_TYPE_UINT32
: {
1075 uint32_t u
, *p
= userdata
;
1077 r
= sd_bus_message_read_basic(m
, type
, &u
);
1085 case SD_BUS_TYPE_INT64
:
1086 case SD_BUS_TYPE_UINT64
: {
1087 uint64_t t
, *p
= userdata
;
1089 r
= sd_bus_message_read_basic(m
, type
, &t
);
1097 case SD_BUS_TYPE_DOUBLE
: {
1098 double d
, *p
= userdata
;
1100 r
= sd_bus_message_read_basic(m
, type
, &d
);
1111 int bus_message_map_all_properties(
1113 const struct bus_properties_map
*map
,
1114 sd_bus_error
*error
,
1122 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1126 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1127 const struct bus_properties_map
*prop
;
1129 const char *contents
;
1133 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1137 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1138 if (streq(map
[i
].member
, member
)) {
1144 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1148 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1152 v
= (uint8_t *)userdata
+ prop
->offset
;
1154 r
= prop
->set(sd_bus_message_get_bus(m
), member
, m
, error
, v
);
1156 r
= map_basic(sd_bus_message_get_bus(m
), member
, m
, error
, v
);
1160 r
= sd_bus_message_exit_container(m
);
1164 r
= sd_bus_message_skip(m
, "v");
1169 r
= sd_bus_message_exit_container(m
);
1176 return sd_bus_message_exit_container(m
);
1179 int bus_message_map_properties_changed(
1181 const struct bus_properties_map
*map
,
1182 sd_bus_error
*error
,
1186 int r
, invalidated
, i
;
1191 r
= bus_message_map_all_properties(m
, map
, error
, userdata
);
1195 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1200 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1201 for (i
= 0; map
[i
].member
; i
++)
1202 if (streq(map
[i
].member
, member
)) {
1209 r
= sd_bus_message_exit_container(m
);
1216 int bus_map_all_properties(
1218 const char *destination
,
1220 const struct bus_properties_map
*map
,
1221 sd_bus_error
*error
,
1224 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1228 assert(destination
);
1232 r
= sd_bus_call_method(
1236 "org.freedesktop.DBus.Properties",
1244 return bus_message_map_all_properties(m
, map
, error
, userdata
);
1247 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**ret
) {
1248 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1251 assert(transport
>= 0);
1252 assert(transport
< _BUS_TRANSPORT_MAX
);
1255 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1256 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1258 switch (transport
) {
1260 case BUS_TRANSPORT_LOCAL
:
1262 r
= sd_bus_default_user(&bus
);
1264 r
= sd_bus_default_system(&bus
);
1268 case BUS_TRANSPORT_REMOTE
:
1269 r
= sd_bus_open_system_remote(&bus
, host
);
1272 case BUS_TRANSPORT_MACHINE
:
1273 r
= sd_bus_open_system_machine(&bus
, host
);
1277 assert_not_reached("Hmm, unknown transport type.");
1282 r
= sd_bus_set_exit_on_disconnect(bus
, true);
1292 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1295 assert(transport
>= 0);
1296 assert(transport
< _BUS_TRANSPORT_MAX
);
1299 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1300 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1302 switch (transport
) {
1304 case BUS_TRANSPORT_LOCAL
:
1306 r
= bus_connect_user_systemd(bus
);
1308 r
= bus_connect_system_systemd(bus
);
1312 case BUS_TRANSPORT_REMOTE
:
1313 r
= sd_bus_open_system_remote(bus
, host
);
1316 case BUS_TRANSPORT_MACHINE
:
1317 r
= sd_bus_open_system_machine(bus
, host
);
1321 assert_not_reached("Hmm, unknown transport type.");
1327 int bus_property_get_bool(
1330 const char *interface
,
1331 const char *property
,
1332 sd_bus_message
*reply
,
1334 sd_bus_error
*error
) {
1336 int b
= *(bool*) userdata
;
1338 return sd_bus_message_append_basic(reply
, 'b', &b
);
1341 int bus_property_set_bool(
1344 const char *interface
,
1345 const char *property
,
1346 sd_bus_message
*value
,
1348 sd_bus_error
*error
) {
1352 r
= sd_bus_message_read(value
, "b", &b
);
1356 *(bool *) userdata
= !!b
;
1360 int bus_property_get_id128(
1363 const char *interface
,
1364 const char *property
,
1365 sd_bus_message
*reply
,
1367 sd_bus_error
*error
) {
1369 sd_id128_t
*id
= userdata
;
1371 if (sd_id128_is_null(*id
)) /* Add an empty array if the ID is zero */
1372 return sd_bus_message_append(reply
, "ay", 0);
1374 return sd_bus_message_append_array(reply
, 'y', id
->bytes
, 16);
1377 #if __SIZEOF_SIZE_T__ != 8
1378 int bus_property_get_size(
1381 const char *interface
,
1382 const char *property
,
1383 sd_bus_message
*reply
,
1385 sd_bus_error
*error
) {
1387 uint64_t sz
= *(size_t*) userdata
;
1389 return sd_bus_message_append_basic(reply
, 't', &sz
);
1393 #if __SIZEOF_LONG__ != 8
1394 int bus_property_get_long(
1397 const char *interface
,
1398 const char *property
,
1399 sd_bus_message
*reply
,
1401 sd_bus_error
*error
) {
1403 int64_t l
= *(long*) userdata
;
1405 return sd_bus_message_append_basic(reply
, 'x', &l
);
1408 int bus_property_get_ulong(
1411 const char *interface
,
1412 const char *property
,
1413 sd_bus_message
*reply
,
1415 sd_bus_error
*error
) {
1417 uint64_t ul
= *(unsigned long*) userdata
;
1419 return sd_bus_message_append_basic(reply
, 't', &ul
);
1423 int bus_log_parse_error(int r
) {
1424 return log_error_errno(r
, "Failed to parse bus message: %m");
1427 int bus_log_create_error(int r
) {
1428 return log_error_errno(r
, "Failed to create bus message: %m");
1432 * bus_path_encode_unique() - encode unique object path
1433 * @b: bus connection or NULL
1434 * @prefix: object path prefix
1435 * @sender_id: unique-name of client, or NULL
1436 * @external_id: external ID to be chosen by client, or NULL
1437 * @ret_path: storage for encoded object path pointer
1439 * Whenever we provide a bus API that allows clients to create and manage
1440 * server-side objects, we need to provide a unique name for these objects. If
1441 * we let the server choose the name, we suffer from a race condition: If a
1442 * client creates an object asynchronously, it cannot destroy that object until
1443 * it received the method reply. It cannot know the name of the new object,
1444 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1446 * Therefore, many APIs allow the client to choose the unique name for newly
1447 * created objects. There're two problems to solve, though:
1448 * 1) Object names are usually defined via dbus object paths, which are
1449 * usually globally namespaced. Therefore, multiple clients must be able
1450 * to choose unique object names without interference.
1451 * 2) If multiple libraries share the same bus connection, they must be
1452 * able to choose unique object names without interference.
1453 * The first problem is solved easily by prefixing a name with the
1454 * unique-bus-name of a connection. The server side must enforce this and
1455 * reject any other name. The second problem is solved by providing unique
1456 * suffixes from within sd-bus.
1458 * This helper allows clients to create unique object-paths. It uses the
1459 * template '/prefix/sender_id/external_id' and returns the new path in
1460 * @ret_path (must be freed by the caller).
1461 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1462 * NULL, this function allocates a unique suffix via @b (by requesting a new
1463 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1466 * Returns: 0 on success, negative error code on failure.
1468 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
1469 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
1470 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
1473 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
1474 assert_return(object_path_is_valid(prefix
), -EINVAL
);
1475 assert_return(ret_path
, -EINVAL
);
1478 r
= sd_bus_get_unique_name(b
, &sender_id
);
1484 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
1485 external_id
= external_buf
;
1488 sender_label
= bus_label_escape(sender_id
);
1492 external_label
= bus_label_escape(external_id
);
1493 if (!external_label
)
1496 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
);
1505 * bus_path_decode_unique() - decode unique object path
1506 * @path: object path to decode
1507 * @prefix: object path prefix
1508 * @ret_sender: output parameter for sender-id label
1509 * @ret_external: output parameter for external-id label
1511 * This does the reverse of bus_path_encode_unique() (see its description for
1512 * details). Both trailing labels, sender-id and external-id, are unescaped and
1513 * returned in the given output parameters (the caller must free them).
1515 * Note that this function returns 0 if the path does not match the template
1516 * (see bus_path_encode_unique()), 1 if it matched.
1518 * Returns: Negative error code on failure, 0 if the given object path does not
1519 * match the template (return parameters are set to NULL), 1 if it was
1520 * parsed successfully (return parameters contain allocated labels).
1522 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
1524 char *sender
, *external
;
1526 assert(object_path_is_valid(path
));
1527 assert(object_path_is_valid(prefix
));
1529 assert(ret_external
);
1531 p
= object_path_startswith(path
, prefix
);
1534 *ret_external
= NULL
;
1541 *ret_external
= NULL
;
1545 sender
= bus_label_unescape_n(p
, q
- p
);
1546 external
= bus_label_unescape(q
+ 1);
1547 if (!sender
|| !external
) {
1553 *ret_sender
= sender
;
1554 *ret_external
= external
;
1558 int bus_property_get_rlimit(
1561 const char *interface
,
1562 const char *property
,
1563 sd_bus_message
*reply
,
1565 sd_bus_error
*error
) {
1570 const char *is_soft
;
1576 is_soft
= endswith(property
, "Soft");
1577 rl
= *(struct rlimit
**) userdata
;
1579 x
= is_soft
? rl
->rlim_cur
: rl
->rlim_max
;
1581 struct rlimit buf
= {};
1585 s
= is_soft
? strndupa(property
, is_soft
- property
) : property
;
1587 z
= rlimit_from_string(strstr(s
, "Limit"));
1591 x
= is_soft
? buf
.rlim_cur
: buf
.rlim_max
;
1594 /* rlim_t might have different sizes, let's map
1595 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1597 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
1599 return sd_bus_message_append(reply
, "t", u
);
1602 int bus_track_add_name_many(sd_bus_track
*t
, char **l
) {
1608 /* Continues adding after failure, and returns the first failure. */
1610 STRV_FOREACH(i
, l
) {
1613 k
= sd_bus_track_add_name(t
, *i
);
1614 if (k
< 0 && r
>= 0)
1621 int bus_open_system_watch_bind(sd_bus
**ret
) {
1622 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
1628 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1630 r
= sd_bus_new(&bus
);
1634 e
= secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1636 e
= DEFAULT_SYSTEM_BUS_ADDRESS
;
1638 r
= sd_bus_set_address(bus
, e
);
1642 r
= sd_bus_set_bus_client(bus
, true);
1646 r
= sd_bus_set_trusted(bus
, true);
1650 r
= sd_bus_negotiate_creds(bus
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
);
1654 r
= sd_bus_set_watch_bind(bus
, true);
1658 r
= sd_bus_set_connected_signal(bus
, true);
1662 r
= sd_bus_start(bus
);