1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "alloc-util.h"
10 #include "bus-internal.h"
11 #include "bus-message.h"
12 #include "bus-signature.h"
16 #include "memfd-util.h"
17 #include "memory-util.h"
18 #include "string-util.h"
20 #include "time-util.h"
23 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
24 static int message_parse_fields(sd_bus_message
*m
);
26 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
31 if (old_base
== new_base
)
34 if ((uint8_t*) p
< (uint8_t*) old_base
)
37 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
40 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
43 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
47 if (part
->memfd
>= 0) {
48 /* erase if requested, but only if the memfd is not sealed yet, i.e. is writable */
49 if (m
->sensitive
&& !m
->sealed
)
50 explicit_bzero_safe(part
->data
, part
->size
);
52 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
53 } else if (part
->munmap_this
)
54 /* We don't erase sensitive data here, since the data is memory mapped from someone else, and
55 * we just don't know if it's OK to write to it */
56 munmap(part
->mmap_begin
, part
->mapped
);
58 /* Erase this if that is requested. Since this is regular memory we know we can write it. */
60 explicit_bzero_safe(part
->data
, part
->size
);
70 static void message_reset_parts(sd_bus_message
*m
) {
71 struct bus_body_part
*part
;
76 while (m
->n_body_parts
> 0) {
77 struct bus_body_part
*next
= part
->next
;
78 message_free_part(m
, part
);
85 m
->cached_rindex_part
= NULL
;
86 m
->cached_rindex_part_begin
= 0;
89 static struct bus_container
*message_get_last_container(sd_bus_message
*m
) {
92 if (m
->n_containers
== 0)
93 return &m
->root_container
;
95 assert(m
->containers
);
96 return m
->containers
+ m
->n_containers
- 1;
99 static void message_free_last_container(sd_bus_message
*m
) {
100 struct bus_container
*c
;
102 c
= message_get_last_container(m
);
105 free(c
->peeked_signature
);
107 /* Move to previous container, but not if we are on root container */
108 if (m
->n_containers
> 0)
112 static void message_reset_containers(sd_bus_message
*m
) {
115 while (m
->n_containers
> 0)
116 message_free_last_container(m
);
118 m
->containers
= mfree(m
->containers
);
119 m
->root_container
.index
= 0;
122 static sd_bus_message
* message_free(sd_bus_message
*m
) {
125 message_reset_parts(m
);
130 /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
131 * reference to the bus message also is considered a reference to the bus connection itself. */
134 close_many(m
->fds
, m
->n_fds
);
138 if (m
->iovec
!= m
->iovec_fixed
)
141 message_reset_containers(m
);
142 assert(m
->n_containers
== 0);
143 message_free_last_container(m
);
145 bus_creds_done(&m
->creds
);
149 static void *message_extend_fields(sd_bus_message
*m
, size_t sz
, bool add_offset
) {
151 size_t old_size
, new_size
, start
;
158 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
159 start
= ALIGN8(old_size
);
160 new_size
= start
+ sz
;
162 if (new_size
< start
|| new_size
> UINT32_MAX
)
165 if (old_size
== new_size
)
166 return (uint8_t*) m
->header
+ old_size
;
168 if (m
->free_header
) {
169 np
= realloc(m
->header
, ALIGN8(new_size
));
173 /* Initially, the header is allocated as part of
174 * the sd_bus_message itself, let's replace it by
177 np
= malloc(ALIGN8(new_size
));
181 memcpy(np
, m
->header
, sizeof(struct bus_header
));
184 /* Zero out padding */
185 if (start
> old_size
)
186 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
190 m
->fields_size
= new_size
- sizeof(struct bus_header
);
192 /* Adjust quick access pointers */
193 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
194 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
195 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
196 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
197 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
198 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
200 m
->free_header
= true;
203 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
206 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
209 return (uint8_t*) np
+ start
;
216 static int message_append_field_string(
228 /* dbus only allows 8-bit header field ids */
232 /* dbus doesn't allow strings over 32-bit */
237 /* Signature "(yv)" where the variant contains "s" */
239 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
240 p
= message_extend_fields(m
, 4 + 4 + l
+ 1, false);
249 ((uint32_t*) p
)[1] = l
;
250 memcpy(p
+ 8, s
, l
+ 1);
253 *ret
= (char*) p
+ 8;
258 static int message_append_field_signature(
269 /* dbus only allows 8-bit header field ids */
273 /* dbus doesn't allow signatures over 8-bit */
275 if (l
> SD_BUS_MAXIMUM_SIGNATURE_LENGTH
)
278 /* Signature "(yv)" where the variant contains "g" */
280 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
281 p
= message_extend_fields(m
, 4 + 1 + l
+ 1, false);
287 p
[2] = SD_BUS_TYPE_SIGNATURE
;
290 memcpy(p
+ 5, s
, l
+ 1);
293 *ret
= (const char*) p
+ 5;
298 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
303 /* dbus only allows 8-bit header field ids */
307 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
308 p
= message_extend_fields(m
, 4 + 4, false);
317 ((uint32_t*) p
)[1] = x
;
322 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
325 /* 64-bit cookies are not supported */
326 if (cookie
> UINT32_MAX
)
329 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
332 static int message_from_header(
339 sd_bus_message
**ret
) {
341 _cleanup_free_ sd_bus_message
*m
= NULL
;
342 struct bus_header
*h
;
343 size_t a
, label_sz
= 0; /* avoid false maybe-uninitialized warning */
346 assert(buffer
|| message_size
<= 0);
347 assert(fds
|| n_fds
<= 0);
350 if (message_size
< sizeof(struct bus_header
))
354 if (!IN_SET(h
->version
, 1, 2))
357 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
360 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
363 /* Note that we are happy with unknown flags in the flags header! */
365 a
= ALIGN(sizeof(sd_bus_message
));
368 label_sz
= strlen(label
);
382 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->fields_size
);
383 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->body_size
);
385 assert(message_size
>= sizeof(struct bus_header
));
386 if (ALIGN8(m
->fields_size
) > message_size
- sizeof(struct bus_header
) ||
387 m
->body_size
!= message_size
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
))
394 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
));
395 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
397 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
401 m
->bus
= sd_bus_ref(bus
);
408 int bus_message_from_malloc(
415 sd_bus_message
**ret
) {
417 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
421 r
= message_from_header(
430 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
433 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
435 m
->body
.sealed
= true;
436 m
->body
.memfd
= -EBADF
;
440 m
->iovec
= m
->iovec_fixed
;
441 m
->iovec
[0] = IOVEC_MAKE(buffer
, length
);
443 r
= message_parse_fields(m
);
447 /* We take possession of the memory and fds now */
448 m
->free_header
= true;
455 _public_
int sd_bus_message_new(
460 assert_return(bus
, -ENOTCONN
);
461 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
462 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
463 assert_return(m
, -EINVAL
);
464 /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
465 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
467 sd_bus_message
*t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
472 t
->bus
= sd_bus_ref(bus
);
473 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
474 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
475 t
->header
->type
= type
;
476 t
->header
->version
= bus
->message_version
;
477 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
479 if (bus
->allow_interactive_authorization
)
480 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
486 _public_
int sd_bus_message_new_signal_to(
489 const char *destination
,
491 const char *interface
,
492 const char *member
) {
494 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
497 assert_return(bus
, -ENOTCONN
);
498 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
499 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
500 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
501 assert_return(object_path_is_valid(path
), -EINVAL
);
502 assert_return(interface_name_is_valid(interface
), -EINVAL
);
503 assert_return(member_name_is_valid(member
), -EINVAL
);
504 assert_return(m
, -EINVAL
);
506 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
512 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
514 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
517 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
520 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
525 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
534 _public_
int sd_bus_message_new_signal(
538 const char *interface
,
539 const char *member
) {
541 return sd_bus_message_new_signal_to(bus
, m
, NULL
, path
, interface
, member
);
544 _public_
int sd_bus_message_new_method_call(
547 const char *destination
,
549 const char *interface
,
550 const char *member
) {
552 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
555 assert_return(bus
, -ENOTCONN
);
556 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
557 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
558 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
559 assert_return(object_path_is_valid(path
), -EINVAL
);
560 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
561 assert_return(member_name_is_valid(member
), -EINVAL
);
562 assert_return(m
, -EINVAL
);
564 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
570 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
573 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
578 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
584 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
593 static int message_new_reply(
594 sd_bus_message
*call
,
596 sd_bus_message
**m
) {
598 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
602 assert_return(call
, -EINVAL
);
603 assert_return(call
->sealed
, -EPERM
);
604 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
605 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
606 assert_return(m
, -EINVAL
);
608 cookie
= BUS_MESSAGE_COOKIE(call
);
612 r
= sd_bus_message_new(call
->bus
, &t
, type
);
618 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
619 t
->reply_cookie
= cookie
;
620 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
625 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
630 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
631 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
633 /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
634 * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
635 * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
636 * to both the message call and the reply. */
637 t
->sensitive
= call
->sensitive
;
643 _public_
int sd_bus_message_new_method_return(
644 sd_bus_message
*call
,
645 sd_bus_message
**m
) {
647 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
650 _public_
int sd_bus_message_new_method_error(
651 sd_bus_message
*call
,
653 const sd_bus_error
*e
) {
655 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
658 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
659 assert_return(m
, -EINVAL
);
661 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
665 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
670 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
675 t
->error
._need_free
= -1;
681 _public_
int sd_bus_message_new_method_errorf(
682 sd_bus_message
*call
,
688 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
691 assert_return(name
, -EINVAL
);
692 assert_return(m
, -EINVAL
);
694 va_start(ap
, format
);
695 sd_bus_error_setfv(&error
, name
, format
, ap
);
698 return sd_bus_message_new_method_error(call
, m
, &error
);
701 _public_
int sd_bus_message_new_method_errno(
702 sd_bus_message
*call
,
705 const sd_bus_error
*p
) {
707 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
709 if (sd_bus_error_is_set(p
))
710 return sd_bus_message_new_method_error(call
, m
, p
);
712 sd_bus_error_set_errno(&berror
, error
);
714 return sd_bus_message_new_method_error(call
, m
, &berror
);
717 _public_
int sd_bus_message_new_method_errnof(
718 sd_bus_message
*call
,
724 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
727 va_start(ap
, format
);
728 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
731 return sd_bus_message_new_method_error(call
, m
, &berror
);
734 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
738 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
739 m
->creds
.well_known_names_local
= true;
740 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
743 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
747 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
748 m
->creds
.well_known_names_driver
= true;
749 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
752 int bus_message_new_synthetic_error(
755 const sd_bus_error
*e
,
756 sd_bus_message
**m
) {
758 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
762 assert(sd_bus_error_is_set(e
));
765 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
771 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
772 t
->reply_cookie
= cookie
;
774 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
778 if (bus
&& bus
->unique_name
) {
779 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
784 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
789 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
794 t
->error
._need_free
= -1;
796 bus_message_set_sender_driver(bus
, t
);
802 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
806 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
807 * least one bus connection object. */
808 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
812 /* Each user reference to a bus message shall also be considered a ref on the bus */
817 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
821 assert(m
->n_ref
> 0);
823 sd_bus_unref(m
->bus
); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
824 * here. Note we have to do this before decrementing our own n_ref here, since
825 * otherwise, if this message is currently queued sd_bus_unref() might call
826 * bus_message_unref_queued() for this which might then destroy the message
827 * while we are still processing it. */
830 if (m
->n_ref
> 0 || m
->n_queued
> 0)
833 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
834 * to reset the field only after the last reference to the bus is dropped, after all we might keep
835 * multiple references to the bus, once for each reference kept on ourselves. */
838 return message_free(m
);
841 sd_bus_message
* bus_message_ref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
845 /* If this is a different bus than the message is associated with, then implicitly turn this into a
846 * regular reference. This means that you can create a memory leak by enqueuing a message generated
847 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
848 * as we'll not detect the cyclic references there. */
850 return sd_bus_message_ref(m
);
852 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
858 sd_bus_message
* bus_message_unref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
863 return sd_bus_message_unref(m
);
865 assert(m
->n_queued
> 0);
868 if (m
->n_ref
> 0 || m
->n_queued
> 0)
873 return message_free(m
);
876 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
877 assert_return(m
, -EINVAL
);
878 assert_return(type
, -EINVAL
);
880 *type
= m
->header
->type
;
884 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
887 assert_return(m
, -EINVAL
);
888 assert_return(cookie
, -EINVAL
);
890 c
= BUS_MESSAGE_COOKIE(m
);
894 *cookie
= BUS_MESSAGE_COOKIE(m
);
898 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
899 assert_return(m
, -EINVAL
);
900 assert_return(cookie
, -EINVAL
);
902 if (m
->reply_cookie
== 0)
905 *cookie
= m
->reply_cookie
;
909 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
910 assert_return(m
, -EINVAL
);
912 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
913 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
916 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
917 assert_return(m
, -EINVAL
);
919 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
922 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
923 assert_return(m
, -EINVAL
);
925 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
926 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
929 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
930 assert_return(m
, NULL
);
935 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
936 assert_return(m
, NULL
);
941 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
942 assert_return(m
, NULL
);
947 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
948 assert_return(m
, NULL
);
950 return m
->destination
;
953 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
954 assert_return(m
, NULL
);
959 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
960 assert_return(m
, NULL
);
962 if (!sd_bus_error_is_set(&m
->error
))
968 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
969 assert_return(m
, -EINVAL
);
970 assert_return(usec
, -EINVAL
);
972 if (m
->monotonic
<= 0)
975 *usec
= m
->monotonic
;
979 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
980 assert_return(m
, -EINVAL
);
981 assert_return(usec
, -EINVAL
);
983 if (m
->realtime
<= 0)
990 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
991 assert_return(m
, -EINVAL
);
992 assert_return(seqnum
, -EINVAL
);
1001 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1002 assert_return(m
, NULL
);
1004 if (m
->creds
.mask
== 0)
1010 _public_
int sd_bus_message_is_signal(
1012 const char *interface
,
1013 const char *member
) {
1015 assert_return(m
, -EINVAL
);
1017 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1020 if (interface
&& !streq_ptr(m
->interface
, interface
))
1023 if (member
&& !streq_ptr(m
->member
, member
))
1029 _public_
int sd_bus_message_is_method_call(
1031 const char *interface
,
1032 const char *member
) {
1034 assert_return(m
, -EINVAL
);
1036 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1039 if (interface
&& !streq_ptr(m
->interface
, interface
))
1042 if (member
&& !streq_ptr(m
->member
, member
))
1048 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1049 assert_return(m
, -EINVAL
);
1051 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1054 if (name
&& !streq_ptr(m
->error
.name
, name
))
1060 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1061 assert_return(m
, -EINVAL
);
1062 assert_return(!m
->sealed
, -EPERM
);
1063 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1065 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1070 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1071 assert_return(m
, -EINVAL
);
1072 assert_return(!m
->sealed
, -EPERM
);
1074 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1079 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1080 assert_return(m
, -EINVAL
);
1081 assert_return(!m
->sealed
, -EPERM
);
1083 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1088 static struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1089 struct bus_body_part
*part
;
1096 if (m
->n_body_parts
<= 0) {
1100 assert(m
->body_end
);
1102 part
= new0(struct bus_body_part
, 1);
1108 m
->body_end
->next
= part
;
1111 part
->memfd
= -EBADF
;
1118 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1123 /* All other fields can be left in their defaults */
1124 assert(!part
->data
);
1125 assert(part
->memfd
< 0);
1128 part
->is_zero
= true;
1129 part
->sealed
= true;
1132 static int part_make_space(
1133 struct sd_bus_message
*m
,
1134 struct bus_body_part
*part
,
1142 assert(!part
->sealed
);
1147 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1148 size_t new_allocated
;
1150 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1151 n
= realloc(part
->data
, new_allocated
);
1158 part
->allocated
= new_allocated
;
1159 part
->free_this
= true;
1163 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1169 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1175 if (m
->n_containers
<= 0)
1178 /* Update counters */
1179 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1181 *c
->array_size
+= expand
;
1184 static void *message_extend_body(
1189 size_t start_body
, end_body
, padding
, added
;
1200 start_body
= ALIGN_TO(m
->body_size
, align
);
1201 end_body
= start_body
+ sz
;
1203 padding
= start_body
- m
->body_size
;
1204 added
= padding
+ sz
;
1206 /* Check for 32-bit overflows */
1207 if (end_body
< start_body
|| end_body
> UINT32_MAX
) {
1213 struct bus_body_part
*part
= NULL
;
1217 m
->n_body_parts
<= 0 ||
1218 m
->body_end
->sealed
||
1219 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
);
1220 /* If this must be an inlined extension, let's create a new part if
1221 * the previous part is large enough to be inlined. */
1225 part
= message_append_part(m
);
1229 part_zero(part
, padding
);
1232 part
= message_append_part(m
);
1236 r
= part_make_space(m
, part
, sz
, &p
);
1241 size_t os
, start_part
, end_part
;
1247 start_part
= ALIGN_TO(part
->size
, align
);
1248 end_part
= start_part
+ sz
;
1250 r
= part_make_space(m
, part
, end_part
, &p
);
1255 memzero(p
, padding
);
1256 p
= (uint8_t*) p
+ padding
;
1259 /* Readjust pointers */
1260 if (m
->n_containers
> 0)
1261 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1262 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1264 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1267 /* Return something that is not NULL and is aligned */
1268 p
= (uint8_t*) align
;
1270 m
->body_size
= end_body
;
1271 message_extend_containers(m
, added
);
1276 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1287 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1291 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1299 m
->fds
[m
->n_fds
] = copy
;
1305 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1306 _cleanup_close_
int fd
= -EBADF
;
1307 struct bus_container
*c
;
1312 assert_return(m
, -EINVAL
);
1313 assert_return(!m
->sealed
, -EPERM
);
1314 assert_return(bus_type_is_basic(type
), -EINVAL
);
1315 assert_return(!m
->poisoned
, -ESTALE
);
1317 c
= message_get_last_container(m
);
1319 if (c
->signature
&& c
->signature
[c
->index
]) {
1320 /* Container signature is already set */
1322 if (c
->signature
[c
->index
] != type
)
1327 /* Maybe we can append to the signature? But only if this is the top-level container */
1328 if (c
->enclosing
!= 0)
1331 e
= strextend(&c
->signature
, CHAR_TO_STR(type
));
1340 case SD_BUS_TYPE_STRING
:
1341 /* To make things easy we'll serialize a NULL string
1342 * into the empty string */
1345 if (!utf8_is_valid(p
))
1349 sz
= 4 + strlen(p
) + 1;
1352 case SD_BUS_TYPE_OBJECT_PATH
:
1357 if (!object_path_is_valid(p
))
1361 sz
= 4 + strlen(p
) + 1;
1364 case SD_BUS_TYPE_SIGNATURE
:
1368 if (!signature_is_valid(p
, /* allow_dict_entry = */ true))
1372 sz
= 1 + strlen(p
) + 1;
1375 case SD_BUS_TYPE_BOOLEAN
:
1377 u32
= p
&& *(int*) p
;
1383 case SD_BUS_TYPE_UNIX_FD
:
1388 fd
= message_push_fd(m
, *(int*) p
);
1399 align
= bus_type_get_alignment(type
);
1400 sz
= bus_type_get_size(type
);
1407 a
= message_extend_body(m
, align
, sz
);
1411 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1412 *(uint32_t*) a
= sz
- 5;
1413 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1416 *stored
= (const uint8_t*) a
+ 4;
1418 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1419 *(uint8_t*) a
= sz
- 2;
1420 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1423 *stored
= (const uint8_t*) a
+ 1;
1431 if (type
== SD_BUS_TYPE_UNIX_FD
)
1434 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1441 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1442 return message_append_basic(m
, type
, p
, NULL
);
1445 _public_
int sd_bus_message_append_string_space(
1450 struct bus_container
*c
;
1453 assert_return(m
, -EINVAL
);
1454 assert_return(s
, -EINVAL
);
1455 assert_return(!m
->sealed
, -EPERM
);
1456 assert_return(!m
->poisoned
, -ESTALE
);
1458 c
= message_get_last_container(m
);
1460 if (c
->signature
&& c
->signature
[c
->index
]) {
1461 /* Container signature is already set */
1463 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1468 /* Maybe we can append to the signature? But only if this is the top-level container */
1469 if (c
->enclosing
!= 0)
1472 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
));
1479 a
= message_extend_body(m
, 4, 4 + size
+ 1);
1483 *(uint32_t*) a
= size
;
1488 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1494 _public_
int sd_bus_message_append_string_iovec(
1496 const struct iovec
*iov
,
1497 unsigned n
/* should be size_t, but is API now… 😞 */) {
1504 assert_return(m
, -EINVAL
);
1505 assert_return(!m
->sealed
, -EPERM
);
1506 assert_return(iov
|| n
== 0, -EINVAL
);
1507 assert_return(!m
->poisoned
, -ESTALE
);
1509 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1511 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1515 for (i
= 0; i
< n
; i
++) {
1517 if (iov
[i
].iov_base
)
1518 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1520 memset(p
, ' ', iov
[i
].iov_len
);
1522 p
+= iov
[i
].iov_len
;
1528 static int bus_message_open_array(
1530 struct bus_container
*c
,
1531 const char *contents
,
1532 uint32_t **array_size
,
1539 struct bus_body_part
*o
;
1547 if (!signature_is_single(contents
, true))
1550 if (c
->signature
&& c
->signature
[c
->index
]) {
1552 /* Verify the existing signature */
1554 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1557 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1560 nindex
= c
->index
+ 1 + strlen(contents
);
1564 if (c
->enclosing
!= 0)
1567 /* Extend the existing signature */
1569 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
);
1575 nindex
= e
- c
->signature
;
1578 alignment
= bus_type_get_alignment(contents
[0]);
1582 a
= message_extend_body(m
, 4, 4);
1587 op
= m
->body_end
->data
;
1588 os
= m
->body_end
->size
;
1590 /* Add alignment between size and first element */
1591 if (!message_extend_body(m
, alignment
, 0))
1594 /* location of array size might have changed so let's readjust a */
1595 if (o
== m
->body_end
)
1596 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1601 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1607 static int bus_message_open_variant(
1609 struct bus_container
*c
,
1610 const char *contents
) {
1619 if (!signature_is_single(contents
, false))
1622 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1625 if (c
->signature
&& c
->signature
[c
->index
]) {
1627 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1633 if (c
->enclosing
!= 0)
1636 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
));
1643 l
= strlen(contents
);
1644 a
= message_extend_body(m
, 1, 1 + l
+ 1);
1649 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1651 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1657 static int bus_message_open_struct(
1659 struct bus_container
*c
,
1660 const char *contents
,
1670 if (!signature_is_valid(contents
, false))
1673 if (c
->signature
&& c
->signature
[c
->index
]) {
1676 l
= strlen(contents
);
1678 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1679 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1680 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1683 nindex
= c
->index
+ 1 + l
+ 1;
1687 if (c
->enclosing
!= 0)
1690 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
));
1696 nindex
= e
- c
->signature
;
1699 /* Align contents to 8 byte boundary */
1700 if (!message_extend_body(m
, 8, 0))
1703 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1709 static int bus_message_open_dict_entry(
1711 struct bus_container
*c
,
1712 const char *contents
,
1720 if (!signature_is_pair(contents
))
1723 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1726 if (c
->signature
&& c
->signature
[c
->index
]) {
1729 l
= strlen(contents
);
1731 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1732 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1733 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1738 /* Align contents to 8 byte boundary */
1739 if (!message_extend_body(m
, 8, 0))
1745 _public_
int sd_bus_message_open_container(
1748 const char *contents
) {
1750 struct bus_container
*c
;
1751 uint32_t *array_size
= NULL
;
1752 _cleanup_free_
char *signature
= NULL
;
1753 size_t before
, begin
= 0;
1756 assert_return(m
, -EINVAL
);
1757 assert_return(!m
->sealed
, -EPERM
);
1758 assert_return(contents
, -EINVAL
);
1759 assert_return(!m
->poisoned
, -ESTALE
);
1761 /* Make sure we have space for one more container */
1762 if (!GREEDY_REALLOC(m
->containers
, m
->n_containers
+ 1)) {
1767 c
= message_get_last_container(m
);
1769 signature
= strdup(contents
);
1775 /* Save old index in the parent container, in case we have to
1776 * abort this container */
1777 c
->saved_index
= c
->index
;
1778 before
= m
->body_size
;
1780 if (type
== SD_BUS_TYPE_ARRAY
)
1781 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
);
1782 else if (type
== SD_BUS_TYPE_VARIANT
)
1783 r
= bus_message_open_variant(m
, c
, contents
);
1784 else if (type
== SD_BUS_TYPE_STRUCT
)
1785 r
= bus_message_open_struct(m
, c
, contents
, &begin
);
1786 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
1787 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
);
1793 /* OK, let's fill it in */
1794 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
1796 .signature
= TAKE_PTR(signature
),
1797 .array_size
= array_size
,
1805 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
1806 struct bus_container
*c
;
1808 assert_return(m
, -EINVAL
);
1809 assert_return(!m
->sealed
, -EPERM
);
1810 assert_return(m
->n_containers
> 0, -EINVAL
);
1811 assert_return(!m
->poisoned
, -ESTALE
);
1813 c
= message_get_last_container(m
);
1815 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1816 if (c
->signature
&& c
->signature
[c
->index
] != 0)
1832 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
1839 stack
[*i
].types
= types
;
1840 stack
[*i
].n_struct
= n_struct
;
1841 stack
[*i
].n_array
= n_array
;
1847 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
1858 *types
= stack
[*i
].types
;
1859 *n_struct
= stack
[*i
].n_struct
;
1860 *n_array
= stack
[*i
].n_array
;
1865 _public_
int sd_bus_message_appendv(
1870 unsigned n_array
, n_struct
;
1871 TypeStack stack
[BUS_CONTAINER_DEPTH
];
1872 unsigned stack_ptr
= 0;
1875 assert_return(m
, -EINVAL
);
1876 assert_return(types
, -EINVAL
);
1877 assert_return(!m
->sealed
, -EPERM
);
1878 assert_return(!m
->poisoned
, -ESTALE
);
1881 n_struct
= strlen(types
);
1886 if (n_array
== 0 || (n_array
== UINT_MAX
&& n_struct
== 0)) {
1887 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
1893 r
= sd_bus_message_close_container(m
);
1901 if (n_array
!= UINT_MAX
)
1910 case SD_BUS_TYPE_BYTE
: {
1913 x
= (uint8_t) va_arg(ap
, int);
1914 r
= sd_bus_message_append_basic(m
, *t
, &x
);
1918 case SD_BUS_TYPE_BOOLEAN
:
1919 case SD_BUS_TYPE_INT32
:
1920 case SD_BUS_TYPE_UINT32
:
1921 case SD_BUS_TYPE_UNIX_FD
: {
1924 /* We assume a boolean is the same as int32_t */
1925 assert_cc(sizeof(int32_t) == sizeof(int));
1927 x
= va_arg(ap
, uint32_t);
1928 r
= sd_bus_message_append_basic(m
, *t
, &x
);
1932 case SD_BUS_TYPE_INT16
:
1933 case SD_BUS_TYPE_UINT16
: {
1936 x
= (uint16_t) va_arg(ap
, int);
1937 r
= sd_bus_message_append_basic(m
, *t
, &x
);
1941 case SD_BUS_TYPE_INT64
:
1942 case SD_BUS_TYPE_UINT64
: {
1945 x
= va_arg(ap
, uint64_t);
1946 r
= sd_bus_message_append_basic(m
, *t
, &x
);
1950 case SD_BUS_TYPE_DOUBLE
: {
1953 x
= va_arg(ap
, double);
1954 r
= sd_bus_message_append_basic(m
, *t
, &x
);
1958 case SD_BUS_TYPE_STRING
:
1959 case SD_BUS_TYPE_OBJECT_PATH
:
1960 case SD_BUS_TYPE_SIGNATURE
: {
1963 x
= va_arg(ap
, const char*);
1964 r
= sd_bus_message_append_basic(m
, *t
, x
);
1968 case SD_BUS_TYPE_ARRAY
: {
1971 r
= signature_element_length(t
+ 1, &k
);
1977 memcpy(s
, t
+ 1, k
);
1980 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
1985 if (n_array
== UINT_MAX
) {
1990 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
1996 n_array
= va_arg(ap
, unsigned);
2001 case SD_BUS_TYPE_VARIANT
: {
2004 s
= va_arg(ap
, const char*);
2008 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2012 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2017 n_struct
= strlen(s
);
2023 case SD_BUS_TYPE_STRUCT_BEGIN
:
2024 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2027 r
= signature_element_length(t
, &k
);
2036 memcpy(s
, t
+ 1, k
- 2);
2039 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2044 if (n_array
== UINT_MAX
) {
2049 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2071 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2075 va_start(ap
, types
);
2076 r
= sd_bus_message_appendv(m
, types
, ap
);
2082 _public_
int sd_bus_message_append_array_space(
2092 assert_return(m
, -EINVAL
);
2093 assert_return(!m
->sealed
, -EPERM
);
2094 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2095 assert_return(ptr
|| size
== 0, -EINVAL
);
2096 assert_return(!m
->poisoned
, -ESTALE
);
2098 align
= bus_type_get_alignment(type
);
2099 sz
= bus_type_get_size(type
);
2101 assert_se(align
> 0);
2107 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2111 a
= message_extend_body(m
, align
, size
);
2115 r
= sd_bus_message_close_container(m
);
2123 _public_
int sd_bus_message_append_array(
2131 assert_return(m
, -EINVAL
);
2132 assert_return(!m
->sealed
, -EPERM
);
2133 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2134 assert_return(ptr
|| size
== 0, -EINVAL
);
2135 assert_return(!m
->poisoned
, -ESTALE
);
2137 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2141 memcpy_safe(p
, ptr
, size
);
2146 _public_
int sd_bus_message_append_array_iovec(
2149 const struct iovec
*iov
,
2150 unsigned n
/* should be size_t, but is API now… 😞 */) {
2157 assert_return(m
, -EINVAL
);
2158 assert_return(!m
->sealed
, -EPERM
);
2159 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2160 assert_return(iov
|| n
== 0, -EINVAL
);
2161 assert_return(!m
->poisoned
, -ESTALE
);
2163 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2165 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2169 for (i
= 0; i
< n
; i
++) {
2171 if (iov
[i
].iov_base
)
2172 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2174 memzero(p
, iov
[i
].iov_len
);
2176 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2182 _public_
int sd_bus_message_append_array_memfd(
2189 _cleanup_close_
int copy_fd
= -EBADF
;
2190 struct bus_body_part
*part
;
2196 assert_return(m
, -EINVAL
);
2197 assert_return(memfd
>= 0, -EBADF
);
2198 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2199 assert_return(size
> 0, -EINVAL
);
2200 assert_return(!m
->sealed
, -EPERM
);
2201 assert_return(!m
->poisoned
, -ESTALE
);
2203 r
= memfd_set_sealed(memfd
);
2207 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2211 r
= memfd_get_size(memfd
, &real_size
);
2215 if (offset
== 0 && size
== UINT64_MAX
)
2217 else if (offset
+ size
> real_size
)
2220 align
= bus_type_get_alignment(type
);
2221 sz
= bus_type_get_size(type
);
2223 assert_se(align
> 0);
2226 if (offset
% align
!= 0)
2232 if (size
> (uint64_t) UINT32_MAX
)
2235 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2239 a
= message_extend_body(m
, align
, 0);
2243 part
= message_append_part(m
);
2247 part
->memfd
= copy_fd
;
2248 part
->memfd_offset
= offset
;
2249 part
->sealed
= true;
2253 m
->body_size
+= size
;
2254 message_extend_containers(m
, size
);
2256 return sd_bus_message_close_container(m
);
2259 _public_
int sd_bus_message_append_string_memfd(
2265 _cleanup_close_
int copy_fd
= -EBADF
;
2266 struct bus_body_part
*part
;
2267 struct bus_container
*c
;
2272 assert_return(m
, -EINVAL
);
2273 assert_return(memfd
>= 0, -EBADF
);
2274 assert_return(size
> 0, -EINVAL
);
2275 assert_return(!m
->sealed
, -EPERM
);
2276 assert_return(!m
->poisoned
, -ESTALE
);
2278 r
= memfd_set_sealed(memfd
);
2282 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2286 r
= memfd_get_size(memfd
, &real_size
);
2290 if (offset
== 0 && size
== UINT64_MAX
)
2292 else if (offset
+ size
> real_size
)
2295 /* We require this to be NUL terminated */
2299 if (size
> (uint64_t) UINT32_MAX
)
2302 c
= message_get_last_container(m
);
2303 if (c
->signature
&& c
->signature
[c
->index
]) {
2304 /* Container signature is already set */
2306 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2311 /* Maybe we can append to the signature? But only if this is the top-level container */
2312 if (c
->enclosing
!= 0)
2315 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
));
2322 a
= message_extend_body(m
, 4, 4);
2326 *(uint32_t*) a
= size
- 1;
2328 part
= message_append_part(m
);
2332 part
->memfd
= copy_fd
;
2333 part
->memfd_offset
= offset
;
2334 part
->sealed
= true;
2338 m
->body_size
+= size
;
2339 message_extend_containers(m
, size
);
2341 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2347 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2350 assert_return(m
, -EINVAL
);
2351 assert_return(!m
->sealed
, -EPERM
);
2352 assert_return(!m
->poisoned
, -ESTALE
);
2354 r
= sd_bus_message_open_container(m
, 'a', "s");
2358 STRV_FOREACH(i
, l
) {
2359 r
= sd_bus_message_append_basic(m
, 's', *i
);
2364 return sd_bus_message_close_container(m
);
2367 static int bus_message_close_header(sd_bus_message
*m
) {
2370 /* The actual user data is finished now, we just complete the variant and struct now. Remember
2371 * this position, so that during parsing we know where to put the outer container end. */
2372 m
->user_body_size
= m
->body_size
;
2374 m
->header
->fields_size
= m
->fields_size
;
2375 m
->header
->body_size
= m
->body_size
;
2380 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2381 struct bus_body_part
*part
;
2386 assert_return(m
, -EINVAL
);
2391 if (m
->n_containers
> 0)
2397 if (cookie
> UINT32_MAX
)
2400 /* In vtables the return signature of method calls is listed,
2401 * let's check if they match if this is a response */
2402 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2403 m
->enforced_reply_signature
&&
2404 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2407 /* If there's a non-trivial signature set, then add it in here */
2408 if (!isempty(m
->root_container
.signature
)) {
2409 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2415 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2420 r
= bus_message_close_header(m
);
2424 m
->header
->serial
= (uint32_t) cookie
;
2426 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2428 /* Add padding at the end of the fields part, since we know
2429 * the body needs to start at an 8 byte alignment. We made
2430 * sure we allocated enough space for this, so all we need to
2431 * do here is to zero it out. */
2432 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2434 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2436 /* If this is something we can send as memfd, then let's seal
2437 the memfd now. Note that we can send memfds as payload only
2438 for directed messages, and not for broadcasts. */
2439 if (m
->destination
&& m
->bus
->use_memfd
) {
2440 MESSAGE_FOREACH_PART(part
, i
, m
)
2441 if (part
->memfd
>= 0 &&
2443 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2444 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2447 /* Try to seal it if that makes
2448 * sense. First, unmap our own map to
2449 * make sure we don't keep it busy. */
2450 bus_body_part_unmap(part
);
2452 /* Then, sync up real memfd size */
2454 r
= memfd_set_size(part
->memfd
, sz
);
2458 /* Finally, try to seal */
2459 if (memfd_set_sealed(part
->memfd
) >= 0)
2460 part
->sealed
= true;
2464 m
->root_container
.end
= m
->user_body_size
;
2465 m
->root_container
.index
= 0;
2472 int bus_body_part_map(struct bus_body_part
*part
) {
2481 if (part
->size
<= 0)
2484 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2485 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2486 static const uint8_t zeroes
[7] = { };
2487 part
->data
= (void*) zeroes
;
2491 shift
= PAGE_OFFSET(part
->memfd_offset
);
2492 psz
= PAGE_ALIGN(part
->size
+ shift
);
2493 if (psz
>= SIZE_MAX
)
2496 if (part
->memfd
>= 0)
2497 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2498 else if (part
->is_zero
)
2499 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2503 if (p
== MAP_FAILED
)
2507 part
->mmap_begin
= p
;
2508 part
->data
= (uint8_t*) p
+ shift
;
2509 part
->munmap_this
= true;
2514 void bus_body_part_unmap(struct bus_body_part
*part
) {
2518 if (part
->memfd
< 0)
2521 if (!part
->mmap_begin
)
2524 if (!part
->munmap_this
)
2527 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
2529 part
->mmap_begin
= NULL
;
2532 part
->munmap_this
= false;
2537 static bool message_end_of_signature(sd_bus_message
*m
) {
2538 struct bus_container
*c
;
2542 c
= message_get_last_container(m
);
2543 return !c
->signature
|| c
->signature
[c
->index
] == 0;
2546 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
2547 struct bus_container
*c
;
2551 c
= message_get_last_container(m
);
2552 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2555 assert(c
->array_size
);
2556 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
2559 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
2560 assert_return(m
, -EINVAL
);
2561 assert_return(m
->sealed
, -EPERM
);
2563 if (complete
&& m
->n_containers
> 0)
2566 if (message_end_of_signature(m
))
2569 if (message_end_of_array(m
, m
->rindex
))
2575 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
2576 struct bus_body_part
*part
;
2582 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
2583 part
= m
->cached_rindex_part
;
2584 begin
= m
->cached_rindex_part_begin
;
2594 if (index
+ sz
<= begin
+ part
->size
) {
2596 r
= bus_body_part_map(part
);
2601 *p
= part
->data
? (uint8_t*) part
->data
+ index
- begin
2602 : NULL
; /* Avoid dereferencing a NULL pointer. */
2604 m
->cached_rindex_part
= part
;
2605 m
->cached_rindex_part_begin
= begin
;
2610 begin
+= part
->size
;
2617 static int message_peek_body(
2624 size_t k
, start
, end
, padding
;
2625 struct bus_body_part
*part
;
2632 start
= ALIGN_TO(*rindex
, align
);
2633 if (start
> m
->user_body_size
)
2636 padding
= start
- *rindex
;
2638 /* Avoid overflow below */
2639 if (nbytes
> SIZE_MAX
- start
)
2642 end
= start
+ nbytes
;
2643 if (end
> m
->user_body_size
)
2646 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
2651 /* Verify padding */
2652 for (k
= 0; k
< padding
; k
++)
2657 part
= find_part(m
, start
, nbytes
, (void**) &q
);
2658 if (!part
|| (nbytes
> 0 && !q
))
2669 static bool validate_nul(const char *s
, size_t l
) {
2671 /* Check for NUL chars in the string */
2672 if (memchr(s
, 0, l
))
2675 /* Check for NUL termination */
2682 static bool validate_string(const char *s
, size_t l
) {
2684 if (!validate_nul(s
, l
))
2687 /* Check if valid UTF8 */
2688 if (!utf8_is_valid(s
))
2694 static bool validate_signature(const char *s
, size_t l
) {
2696 if (!validate_nul(s
, l
))
2699 /* Check if valid signature */
2700 if (!signature_is_valid(s
, true))
2706 static bool validate_object_path(const char *s
, size_t l
) {
2708 if (!validate_nul(s
, l
))
2711 if (!object_path_is_valid(s
))
2717 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
2718 struct bus_container
*c
;
2723 assert_return(m
, -EINVAL
);
2724 assert_return(m
->sealed
, -EPERM
);
2725 assert_return(bus_type_is_basic(type
), -EINVAL
);
2727 if (message_end_of_signature(m
))
2730 if (message_end_of_array(m
, m
->rindex
))
2733 c
= message_get_last_container(m
);
2734 if (c
->signature
[c
->index
] != type
)
2739 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
2743 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
2747 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
2748 if (l
== UINT32_MAX
)
2749 /* avoid overflow right below */
2752 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
2756 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
2757 ok
= validate_object_path(q
, l
);
2759 ok
= validate_string(q
, l
);
2764 *(const char**) p
= q
;
2766 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
2769 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
2775 /* avoid overflow right below */
2778 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
2782 if (!validate_signature(q
, l
))
2786 *(const char**) p
= q
;
2791 align
= bus_type_get_alignment(type
);
2794 sz
= bus_type_get_size(type
);
2797 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
2803 case SD_BUS_TYPE_BYTE
:
2805 *(uint8_t*) p
= *(uint8_t*) q
;
2808 case SD_BUS_TYPE_BOOLEAN
:
2810 *(int*) p
= !!*(uint32_t*) q
;
2813 case SD_BUS_TYPE_INT16
:
2814 case SD_BUS_TYPE_UINT16
:
2816 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
2819 case SD_BUS_TYPE_INT32
:
2820 case SD_BUS_TYPE_UINT32
:
2822 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
2825 case SD_BUS_TYPE_INT64
:
2826 case SD_BUS_TYPE_UINT64
:
2827 case SD_BUS_TYPE_DOUBLE
:
2829 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
2832 case SD_BUS_TYPE_UNIX_FD
: {
2835 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
2840 *(int*) p
= m
->fds
[j
];
2845 assert_not_reached();
2851 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2857 static int bus_message_enter_array(
2859 struct bus_container
*c
,
2860 const char *contents
,
2861 uint32_t **array_size
) {
2872 if (!signature_is_single(contents
, true))
2875 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
2878 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
2881 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
2886 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
2890 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
2893 alignment
= bus_type_get_alignment(contents
[0]);
2897 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
2901 *array_size
= (uint32_t*) q
;
2905 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2906 c
->index
+= 1 + strlen(contents
);
2911 static int bus_message_enter_variant(
2913 struct bus_container
*c
,
2914 const char *contents
) {
2925 if (!signature_is_single(contents
, false))
2928 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
2931 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
2934 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
2939 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
2945 /* avoid overflow right below */
2948 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
2952 if (!validate_signature(q
, l
))
2955 if (!streq(q
, contents
))
2960 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2966 static int bus_message_enter_struct(
2968 struct bus_container
*c
,
2969 const char *contents
) {
2978 if (!signature_is_valid(contents
, false))
2981 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
2984 l
= strlen(contents
);
2986 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
2987 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
2988 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
2991 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
2995 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2996 c
->index
+= 1 + l
+ 1;
3001 static int bus_message_enter_dict_entry(
3003 struct bus_container
*c
,
3004 const char *contents
) {
3013 if (!signature_is_pair(contents
))
3016 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3019 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3022 l
= strlen(contents
);
3024 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3025 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3026 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3029 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3033 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3034 c
->index
+= 1 + l
+ 1;
3039 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3041 const char *contents
) {
3042 struct bus_container
*c
;
3043 uint32_t *array_size
= NULL
;
3044 _cleanup_free_
char *signature
= NULL
;
3048 assert_return(m
, -EINVAL
);
3049 assert_return(m
->sealed
, -EPERM
);
3050 assert_return(type
!= 0 || !contents
, -EINVAL
);
3052 if (type
== 0 || !contents
) {
3056 /* Allow entering into anonymous containers */
3057 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
3061 if (type
!= 0 && type
!= tt
)
3064 if (contents
&& !streq(contents
, cc
))
3072 * We enforce a global limit on container depth, that is much
3073 * higher than the 32 structs and 32 arrays the specification
3074 * mandates. This is simpler to implement for us, and we need
3075 * this only to ensure our container array doesn't grow
3076 * without bounds. We are happy to return any data from a
3077 * message as long as the data itself is valid, even if the
3078 * overall message might be not.
3080 * Note that the message signature is validated when
3081 * parsing the headers, and that validation does check the
3084 * Note that the specification defines no limits on the depth
3085 * of stacked variants, but we do.
3087 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
3090 if (!GREEDY_REALLOC(m
->containers
, m
->n_containers
+ 1))
3093 if (message_end_of_signature(m
))
3096 if (message_end_of_array(m
, m
->rindex
))
3099 c
= message_get_last_container(m
);
3101 signature
= strdup(contents
);
3105 c
->saved_index
= c
->index
;
3108 if (type
== SD_BUS_TYPE_ARRAY
)
3109 r
= bus_message_enter_array(m
, c
, contents
, &array_size
);
3110 else if (type
== SD_BUS_TYPE_VARIANT
)
3111 r
= bus_message_enter_variant(m
, c
, contents
);
3112 else if (type
== SD_BUS_TYPE_STRUCT
)
3113 r
= bus_message_enter_struct(m
, c
, contents
);
3114 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
3115 r
= bus_message_enter_dict_entry(m
, c
, contents
);
3121 /* OK, let's fill it in */
3122 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
3124 .signature
= TAKE_PTR(signature
),
3128 /* Unary type has fixed size of 1, but virtual size of 0 */
3130 .array_size
= array_size
,
3136 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
3137 struct bus_container
*c
;
3139 assert_return(m
, -EINVAL
);
3140 assert_return(m
->sealed
, -EPERM
);
3141 assert_return(m
->n_containers
> 0, -ENXIO
);
3143 c
= message_get_last_container(m
);
3145 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
3146 if (c
->signature
&& c
->signature
[c
->index
] != 0)
3150 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3153 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3154 if (c
->begin
+ l
!= m
->rindex
)
3158 message_free_last_container(m
);
3163 static void message_quit_container(sd_bus_message
*m
) {
3164 struct bus_container
*c
;
3168 assert(m
->n_containers
> 0);
3171 c
= message_get_last_container(m
);
3172 assert(m
->rindex
>= c
->before
);
3173 m
->rindex
= c
->before
;
3175 /* Free container */
3176 message_free_last_container(m
);
3178 /* Correct index of new top-level container */
3179 c
= message_get_last_container(m
);
3180 c
->index
= c
->saved_index
;
3183 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
3184 struct bus_container
*c
;
3187 assert_return(m
, -EINVAL
);
3188 assert_return(m
->sealed
, -EPERM
);
3190 if (message_end_of_signature(m
))
3193 if (message_end_of_array(m
, m
->rindex
))
3196 c
= message_get_last_container(m
);
3198 if (bus_type_is_basic(c
->signature
[c
->index
])) {
3202 *type
= c
->signature
[c
->index
];
3206 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
3211 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
3215 /* signature_element_length does verification internally */
3217 /* The array element must not be empty */
3219 if (free_and_strndup(&c
->peeked_signature
,
3220 c
->signature
+ c
->index
+ 1, l
) < 0)
3223 *contents
= c
->peeked_signature
;
3227 *type
= SD_BUS_TYPE_ARRAY
;
3232 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
3237 r
= signature_element_length(c
->signature
+c
->index
, &l
);
3242 if (free_and_strndup(&c
->peeked_signature
,
3243 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
3246 *contents
= c
->peeked_signature
;
3250 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
3255 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
3261 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3267 /* avoid overflow right below */
3270 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3274 if (!validate_signature(q
, l
))
3281 *type
= SD_BUS_TYPE_VARIANT
;
3296 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
3297 struct bus_container
*c
;
3299 assert_return(m
, -EINVAL
);
3300 assert_return(m
->sealed
, -EPERM
);
3303 message_reset_containers(m
);
3306 c
= message_get_last_container(m
);
3308 c
= message_get_last_container(m
);
3311 m
->rindex
= c
->begin
;
3314 return !isempty(c
->signature
);
3317 _public_
int sd_bus_message_readv(
3322 unsigned n_array
, n_struct
;
3323 TypeStack stack
[BUS_CONTAINER_DEPTH
];
3324 unsigned stack_ptr
= 0;
3325 unsigned n_loop
= 0;
3328 assert_return(m
, -EINVAL
);
3329 assert_return(m
->sealed
, -EPERM
);
3330 assert_return(types
, -EINVAL
);
3335 /* Ideally, we'd just call ourselves recursively on every
3336 * complex type. However, the state of a va_list that is
3337 * passed to a function is undefined after that function
3338 * returns. This means we need to decode the va_list linearly
3339 * in a single stackframe. We hence implement our own
3340 * home-grown stack in an array. */
3342 n_array
= UINT_MAX
; /* length of current array entries */
3343 n_struct
= strlen(types
); /* length of current struct contents signature */
3350 if (n_array
== 0 || (n_array
== UINT_MAX
&& n_struct
== 0)) {
3351 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
3357 r
= sd_bus_message_exit_container(m
);
3365 if (n_array
!= UINT_MAX
)
3374 case SD_BUS_TYPE_BYTE
:
3375 case SD_BUS_TYPE_BOOLEAN
:
3376 case SD_BUS_TYPE_INT16
:
3377 case SD_BUS_TYPE_UINT16
:
3378 case SD_BUS_TYPE_INT32
:
3379 case SD_BUS_TYPE_UINT32
:
3380 case SD_BUS_TYPE_INT64
:
3381 case SD_BUS_TYPE_UINT64
:
3382 case SD_BUS_TYPE_DOUBLE
:
3383 case SD_BUS_TYPE_STRING
:
3384 case SD_BUS_TYPE_OBJECT_PATH
:
3385 case SD_BUS_TYPE_SIGNATURE
:
3386 case SD_BUS_TYPE_UNIX_FD
: {
3389 p
= va_arg(ap
, void*);
3390 r
= sd_bus_message_read_basic(m
, *t
, p
);
3403 case SD_BUS_TYPE_ARRAY
: {
3406 r
= signature_element_length(t
+ 1, &k
);
3412 memcpy(s
, t
+ 1, k
);
3415 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
3426 if (n_array
== UINT_MAX
) {
3431 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
3437 n_array
= va_arg(ap
, unsigned);
3442 case SD_BUS_TYPE_VARIANT
: {
3445 s
= va_arg(ap
, const char *);
3449 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
3459 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
3464 n_struct
= strlen(s
);
3470 case SD_BUS_TYPE_STRUCT_BEGIN
:
3471 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
3474 r
= signature_element_length(t
, &k
);
3482 memcpy(s
, t
+ 1, k
- 2);
3485 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
3495 if (n_array
== UINT_MAX
) {
3500 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
3519 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
3523 va_start(ap
, types
);
3524 r
= sd_bus_message_readv(m
, types
, ap
);
3530 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
3533 assert_return(m
, -EINVAL
);
3534 assert_return(m
->sealed
, -EPERM
);
3536 /* If types is NULL, read exactly one element */
3538 struct bus_container
*c
;
3541 if (message_end_of_signature(m
))
3544 if (message_end_of_array(m
, m
->rindex
))
3547 c
= message_get_last_container(m
);
3549 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
3553 types
= strndupa_safe(c
->signature
+ c
->index
, l
);
3558 case 0: /* Nothing to drop */
3561 case SD_BUS_TYPE_BYTE
:
3562 case SD_BUS_TYPE_BOOLEAN
:
3563 case SD_BUS_TYPE_INT16
:
3564 case SD_BUS_TYPE_UINT16
:
3565 case SD_BUS_TYPE_INT32
:
3566 case SD_BUS_TYPE_UINT32
:
3567 case SD_BUS_TYPE_INT64
:
3568 case SD_BUS_TYPE_UINT64
:
3569 case SD_BUS_TYPE_DOUBLE
:
3570 case SD_BUS_TYPE_STRING
:
3571 case SD_BUS_TYPE_OBJECT_PATH
:
3572 case SD_BUS_TYPE_SIGNATURE
:
3573 case SD_BUS_TYPE_UNIX_FD
:
3575 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
3579 r
= sd_bus_message_skip(m
, types
+ 1);
3585 case SD_BUS_TYPE_ARRAY
: {
3588 r
= signature_element_length(types
+ 1, &k
);
3594 memcpy(s
, types
+1, k
);
3597 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
3602 r
= sd_bus_message_skip(m
, s
);
3609 r
= sd_bus_message_exit_container(m
);
3614 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
3621 case SD_BUS_TYPE_VARIANT
: {
3622 const char *contents
;
3625 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
3629 if (x
!= SD_BUS_TYPE_VARIANT
)
3632 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
3636 r
= sd_bus_message_skip(m
, contents
);
3641 r
= sd_bus_message_exit_container(m
);
3645 r
= sd_bus_message_skip(m
, types
+ 1);
3652 case SD_BUS_TYPE_STRUCT_BEGIN
:
3653 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
3656 r
= signature_element_length(types
, &k
);
3664 memcpy(s
, types
+1, k
-2);
3667 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
3671 r
= sd_bus_message_skip(m
, s
);
3675 r
= sd_bus_message_exit_container(m
);
3680 r
= sd_bus_message_skip(m
, types
+ k
);
3692 _public_
int sd_bus_message_read_array(
3698 struct bus_container
*c
;
3704 assert_return(m
, -EINVAL
);
3705 assert_return(m
->sealed
, -EPERM
);
3706 assert_return(bus_type_is_trivial(type
), -EINVAL
);
3707 assert_return(ptr
, -EINVAL
);
3708 assert_return(size
, -EINVAL
);
3709 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
3711 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
3720 c
= message_get_last_container(m
);
3722 align
= bus_type_get_alignment(type
);
3726 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3729 /* Zero length array, let's return some aligned
3730 * pointer that is not NULL */
3731 p
= (uint8_t*) align
;
3733 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
3738 r
= sd_bus_message_exit_container(m
);
3742 *ptr
= (const void*) p
;
3748 message_quit_container(m
);
3752 static int message_peek_fields(
3765 start
= ALIGN_TO(*rindex
, align
);
3766 if (start
> m
->fields_size
)
3769 /* Avoid overflow below */
3770 if (nbytes
> SIZE_MAX
- start
)
3773 end
= start
+ nbytes
;
3774 if (end
> m
->fields_size
)
3777 /* Verify that padding is 0 */
3778 uint8_t *p
= BUS_MESSAGE_FIELDS(m
);
3779 for (size_t k
= *rindex
; k
< start
; k
++)
3790 static int message_peek_field_uint32(
3802 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
3807 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3812 static int message_peek_field_string(
3814 bool (*validate
)(const char *p
),
3826 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
3830 if (l
== UINT32_MAX
)
3831 /* avoid overflow right below */
3834 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
3839 if (!validate_nul(q
, l
))
3845 if (!validate_string(q
, l
))
3855 static int message_peek_field_signature(
3868 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
3874 /* avoid overflow right below */
3877 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
3881 if (!validate_signature(q
, l
))
3890 static int message_skip_fields(
3893 uint32_t array_size
,
3894 const char **signature
) {
3896 size_t original_index
;
3903 original_index
= *ri
;
3909 if (array_size
!= UINT32_MAX
&&
3910 array_size
<= *ri
- original_index
)
3917 if (t
== SD_BUS_TYPE_STRING
) {
3919 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
3925 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
3927 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
3933 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
3935 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
3941 } else if (bus_type_is_basic(t
)) {
3944 align
= bus_type_get_alignment(t
);
3945 k
= bus_type_get_size(t
);
3946 assert(align
> 0 && k
> 0);
3948 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
3954 } else if (t
== SD_BUS_TYPE_ARRAY
) {
3956 r
= signature_element_length(*signature
+ 1, &l
);
3962 char sig
[l
+ 1], *s
= sig
;
3966 strncpy(sig
, *signature
+ 1, l
);
3969 alignment
= bus_type_get_alignment(sig
[0]);
3973 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
3976 if (nas
> BUS_ARRAY_MAX_SIZE
)
3979 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
3983 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
3988 (*signature
) += 1 + l
;
3990 } else if (t
== SD_BUS_TYPE_VARIANT
) {
3993 r
= message_peek_field_signature(m
, ri
, 0, &s
);
3997 r
= message_skip_fields(m
, ri
, UINT32_MAX
, (const char**) &s
);
4003 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
4005 r
= signature_element_length(*signature
, &l
);
4011 char sig
[l
+ 1], *s
= sig
;
4012 strncpy(sig
, *signature
+ 1, l
);
4015 r
= message_skip_fields(m
, ri
, UINT32_MAX
, (const char**) &s
);
4026 static int message_parse_fields(sd_bus_message
*m
) {
4027 uint32_t unix_fds
= 0;
4028 bool unix_fds_set
= false;
4033 m
->user_body_size
= m
->body_size
;
4035 for (size_t ri
= 0; ri
< m
->fields_size
; ) {
4036 const char *signature
;
4037 uint64_t field_type
;
4038 size_t item_size
= SIZE_MAX
;
4041 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
4047 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
4051 switch (field_type
) {
4053 case _BUS_MESSAGE_HEADER_INVALID
:
4056 case BUS_MESSAGE_HEADER_PATH
:
4061 if (!streq(signature
, "o"))
4064 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
4067 case BUS_MESSAGE_HEADER_INTERFACE
:
4072 if (!streq(signature
, "s"))
4075 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
4078 case BUS_MESSAGE_HEADER_MEMBER
:
4083 if (!streq(signature
, "s"))
4086 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
4089 case BUS_MESSAGE_HEADER_ERROR_NAME
:
4094 if (!streq(signature
, "s"))
4097 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
4099 m
->error
._need_free
= -1;
4103 case BUS_MESSAGE_HEADER_DESTINATION
:
4108 if (!streq(signature
, "s"))
4111 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
4114 case BUS_MESSAGE_HEADER_SENDER
:
4119 if (!streq(signature
, "s"))
4122 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
4124 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
4125 m
->creds
.unique_name
= (char*) m
->sender
;
4126 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
4131 case BUS_MESSAGE_HEADER_SIGNATURE
: {
4135 if (m
->root_container
.signature
)
4138 if (!streq(signature
, "g"))
4141 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
4149 free_and_replace(m
->root_container
.signature
, c
);
4153 case BUS_MESSAGE_HEADER_REPLY_SERIAL
: {
4156 if (m
->reply_cookie
!= 0)
4160 if (!streq(signature
, "u"))
4163 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
4167 m
->reply_cookie
= serial
;
4169 if (m
->reply_cookie
== 0)
4174 case BUS_MESSAGE_HEADER_UNIX_FDS
:
4178 if (!streq(signature
, "u"))
4181 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
4185 unix_fds_set
= true;
4189 r
= message_skip_fields(m
, &ri
, UINT32_MAX
, (const char **) &signature
);
4195 if (m
->n_fds
!= unix_fds
)
4198 switch (m
->header
->type
) {
4200 case SD_BUS_MESSAGE_SIGNAL
:
4201 if (!m
->path
|| !m
->interface
|| !m
->member
)
4204 if (m
->reply_cookie
!= 0)
4209 case SD_BUS_MESSAGE_METHOD_CALL
:
4211 if (!m
->path
|| !m
->member
)
4214 if (m
->reply_cookie
!= 0)
4219 case SD_BUS_MESSAGE_METHOD_RETURN
:
4221 if (m
->reply_cookie
== 0)
4225 case SD_BUS_MESSAGE_METHOD_ERROR
:
4227 if (m
->reply_cookie
== 0 || !m
->error
.name
)
4232 /* Refuse non-local messages that claim they are local */
4233 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
4235 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
4237 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
4240 m
->root_container
.end
= m
->user_body_size
;
4242 /* Try to read the error message, but if we can't it's a non-issue */
4243 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
4244 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
4249 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
4250 assert_return(m
, -EINVAL
);
4251 assert_return(destination
, -EINVAL
);
4252 assert_return(service_name_is_valid(destination
), -EINVAL
);
4253 assert_return(!m
->sealed
, -EPERM
);
4254 assert_return(!m
->destination
, -EEXIST
);
4256 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
4259 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
4260 assert_return(m
, -EINVAL
);
4261 assert_return(sender
, -EINVAL
);
4262 assert_return(service_name_is_valid(sender
), -EINVAL
);
4263 assert_return(!m
->sealed
, -EPERM
);
4264 assert_return(!m
->sender
, -EEXIST
);
4266 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
4269 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
4273 struct bus_body_part
*part
;
4279 total
= BUS_MESSAGE_SIZE(m
);
4285 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
4286 MESSAGE_FOREACH_PART(part
, i
, m
)
4287 e
= mempcpy(e
, part
->data
, part
->size
);
4289 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
4297 _public_
int sd_bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
4299 const char *contents
, *s
;
4305 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
4309 if (type
!= SD_BUS_TYPE_ARRAY
|| !STR_IN_SET(contents
, "s", "o", "g"))
4312 r
= sd_bus_message_enter_container(m
, 'a', NULL
);
4316 /* sd_bus_message_read_basic() does content validation for us. */
4317 while ((r
= sd_bus_message_read_basic(m
, *contents
, &s
)) > 0) {
4318 r
= strv_extend(l
, s
);
4325 r
= sd_bus_message_exit_container(m
);
4332 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
4333 _cleanup_strv_free_
char **strv
= NULL
;
4336 assert_return(m
, -EINVAL
);
4337 assert_return(m
->sealed
, -EPERM
);
4338 assert_return(l
, -EINVAL
);
4340 r
= sd_bus_message_read_strv_extend(m
, &strv
);
4344 *l
= TAKE_PTR(strv
);
4348 static int bus_message_get_arg_skip(
4352 const char **_contents
) {
4357 r
= sd_bus_message_rewind(m
, true);
4362 const char *contents
;
4365 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
4371 /* Don't match against arguments after the first one we don't understand */
4372 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
4373 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
4378 *_contents
= contents
;
4384 r
= sd_bus_message_skip(m
, NULL
);
4391 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
4398 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
4402 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
4405 return sd_bus_message_read_basic(m
, type
, str
);
4408 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
4409 const char *contents
;
4416 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
4420 if (type
!= SD_BUS_TYPE_ARRAY
)
4422 if (!STR_IN_SET(contents
, "s", "o", "g"))
4425 return sd_bus_message_read_strv(m
, strv
);
4428 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
4429 assert_return(m
, EINVAL
);
4431 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
4434 return sd_bus_error_get_errno(&m
->error
);
4437 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
4438 struct bus_container
*c
;
4440 assert_return(m
, NULL
);
4442 c
= complete
? &m
->root_container
: message_get_last_container(m
);
4443 return strempty(c
->signature
);
4446 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
4447 assert_return(m
, -EINVAL
);
4449 return isempty(m
->root_container
.signature
);
4452 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
4453 assert_return(m
, -EINVAL
);
4455 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
4458 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
4459 bool done_something
= false;
4462 assert_return(m
, -EINVAL
);
4463 assert_return(source
, -EINVAL
);
4464 assert_return(!m
->sealed
, -EPERM
);
4465 assert_return(source
->sealed
, -EPERM
);
4468 const char *contents
;
4483 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
4489 done_something
= true;
4491 if (bus_type_is_container(type
) > 0) {
4493 r
= sd_bus_message_enter_container(source
, type
, contents
);
4497 r
= sd_bus_message_open_container(m
, type
, contents
);
4501 r
= sd_bus_message_copy(m
, source
, true);
4505 r
= sd_bus_message_close_container(m
);
4509 r
= sd_bus_message_exit_container(source
);
4516 r
= sd_bus_message_read_basic(source
, type
, &basic
);
4522 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
4523 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
4525 r
= sd_bus_message_append_basic(m
, type
, &basic
);
4532 return done_something
;
4535 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
4540 assert_return(m
, -EINVAL
);
4541 assert_return(m
->sealed
, -EPERM
);
4542 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
4543 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
4544 assert_return(type
|| contents
, -EINVAL
);
4545 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
4547 r
= sd_bus_message_peek_type(m
, &t
, &c
);
4551 if (type
!= 0 && type
!= t
)
4554 if (contents
&& !streq_ptr(contents
, c
))
4560 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
4561 assert_return(m
, NULL
);
4566 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
4567 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
4575 switch ((*m
)->header
->type
) {
4577 case SD_BUS_MESSAGE_SIGNAL
:
4578 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
4584 case SD_BUS_MESSAGE_METHOD_CALL
:
4585 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
4591 case SD_BUS_MESSAGE_METHOD_RETURN
:
4592 case SD_BUS_MESSAGE_METHOD_ERROR
:
4594 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
4600 n
->reply_cookie
= (*m
)->reply_cookie
;
4602 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
4606 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
4607 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
4611 n
->error
._need_free
= -1;
4620 if ((*m
)->destination
&& !n
->destination
) {
4621 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
4626 if ((*m
)->sender
&& !n
->sender
) {
4627 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
4632 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
4634 r
= sd_bus_message_copy(n
, *m
, true);
4638 timeout
= (*m
)->timeout
;
4639 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
4640 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
4645 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
4649 sd_bus_message_unref(*m
);
4655 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
4656 static bool warned
= false;
4658 assert_return(m
, -EINVAL
);
4659 assert_return(priority
, -EINVAL
);
4662 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
4670 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
4671 static bool warned
= false;
4673 assert_return(m
, -EINVAL
);
4674 assert_return(!m
->sealed
, -EPERM
);
4677 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
4684 _public_
int sd_bus_message_sensitive(sd_bus_message
*m
) {
4685 assert_return(m
, -EINVAL
);
4687 m
->sensitive
= true;
4691 char** bus_message_make_log_fields(sd_bus_message
*m
) {
4692 _cleanup_strv_free_
char **strv
= NULL
;
4696 (void) strv_extend_assignment(&strv
, "DBUS_MESSAGE_TYPE", bus_message_type_to_string(m
->header
->type
));
4697 (void) strv_extend_assignment(&strv
, "DBUS_SENDER", sd_bus_message_get_sender(m
));
4698 (void) strv_extend_assignment(&strv
, "DBUS_DESTINATION", sd_bus_message_get_destination(m
));
4699 (void) strv_extend_assignment(&strv
, "DBUS_PATH", sd_bus_message_get_path(m
));
4700 (void) strv_extend_assignment(&strv
, "DBUS_INTERFACE", sd_bus_message_get_interface(m
));
4701 (void) strv_extend_assignment(&strv
, "DBUS_MEMBER", sd_bus_message_get_member(m
));
4703 (void) strv_extendf(&strv
, "DBUS_MESSAGE_COOKIE=%" PRIu64
, BUS_MESSAGE_COOKIE(m
));
4704 if (m
->reply_cookie
!= 0)
4705 (void) strv_extendf(&strv
, "DBUS_MESSAGE_REPLY_COOKIE=%" PRIu64
, m
->reply_cookie
);
4707 (void) strv_extend_assignment(&strv
, "DBUS_SIGNATURE", m
->root_container
.signature
);
4708 (void) strv_extend_assignment(&strv
, "DBUS_ERROR_NAME", m
->error
.name
);
4709 (void) strv_extend_assignment(&strv
, "DBUS_ERROR_MESSAGE", m
->error
.message
);
4711 return TAKE_PTR(strv
);