]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-message.c
man: document sd_id128_string_equal()
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-message.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
de1c301e
LP
2
3#include <errno.h>
2c93b4ef 4#include <fcntl.h>
bc7fd8cd 5#include <sys/mman.h>
de1c301e 6
de1c301e 7#include "sd-bus.h"
07630cea 8
b5efdb8a 9#include "alloc-util.h"
de1c301e 10#include "bus-internal.h"
3ffd4af2 11#include "bus-message.h"
de1c301e 12#include "bus-signature.h"
07630cea 13#include "bus-type.h"
3ffd4af2 14#include "fd-util.h"
afc5dbf3 15#include "io-util.h"
07630cea 16#include "memfd-util.h"
0a970718 17#include "memory-util.h"
07630cea
LP
18#include "string-util.h"
19#include "strv.h"
20#include "time-util.h"
21#include "utf8.h"
de1c301e 22
80a46c73 23static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
75c85c3b 24static int message_parse_fields(sd_bus_message *m);
de1c301e 25
bc7fd8cd
LP
26static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
27
4e361acc 28 if (!p)
bc7fd8cd
LP
29 return NULL;
30
31 if (old_base == new_base)
32 return (void*) p;
33
34 if ((uint8_t*) p < (uint8_t*) old_base)
35 return (void*) p;
36
37 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
38 return (void*) p;
39
40 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
41}
42
43static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
44 assert(m);
45 assert(part);
46
7a77d2a4 47 if (part->memfd >= 0) {
162392b7 48 /* erase if requested, but only if the memfd is not sealed yet, i.e. is writable */
7a77d2a4
LP
49 if (m->sensitive && !m->sealed)
50 explicit_bzero_safe(part->data, part->size);
51
a132bef0 52 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
7a77d2a4
LP
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 */
7dcd79c2 56 munmap(part->mmap_begin, part->mapped);
7a77d2a4
LP
57 else {
58 /* Erase this if that is requested. Since this is regular memory we know we can write it. */
59 if (m->sensitive)
60 explicit_bzero_safe(part->data, part->size);
61
62 if (part->free_this)
63 free(part->data);
64 }
bc7fd8cd
LP
65
66 if (part != &m->body)
67 free(part);
68}
69
70static void message_reset_parts(sd_bus_message *m) {
71 struct bus_body_part *part;
72
73 assert(m);
74
75 part = &m->body;
76 while (m->n_body_parts > 0) {
77 struct bus_body_part *next = part->next;
78 message_free_part(m, part);
79 part = next;
80 m->n_body_parts--;
81 }
82
83 m->body_end = NULL;
84
85 m->cached_rindex_part = NULL;
86 m->cached_rindex_part_begin = 0;
87}
88
9c65778d 89static struct bus_container *message_get_last_container(sd_bus_message *m) {
6d1e0f4f
ZJS
90 assert(m);
91
92 if (m->n_containers == 0)
93 return &m->root_container;
94
95 assert(m->containers);
96 return m->containers + m->n_containers - 1;
97}
98
99static void message_free_last_container(sd_bus_message *m) {
100 struct bus_container *c;
101
9c65778d 102 c = message_get_last_container(m);
6d1e0f4f
ZJS
103
104 free(c->signature);
105 free(c->peeked_signature);
6d1e0f4f
ZJS
106
107 /* Move to previous container, but not if we are on root container */
108 if (m->n_containers > 0)
109 m->n_containers--;
110}
9a17484d 111
6d1e0f4f 112static void message_reset_containers(sd_bus_message *m) {
9a17484d
LP
113 assert(m);
114
6d1e0f4f
ZJS
115 while (m->n_containers > 0)
116 message_free_last_container(m);
9a17484d 117
a1e58e8e 118 m->containers = mfree(m->containers);
9a17484d
LP
119 m->root_container.index = 0;
120}
121
2ab3a635 122static sd_bus_message* message_free(sd_bus_message *m) {
de1c301e
LP
123 assert(m);
124
7a77d2a4
LP
125 message_reset_parts(m);
126
de1c301e
LP
127 if (m->free_header)
128 free(m->header);
129
1b3f9dd7
LP
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. */
f54514f3 132
2c93b4ef
LP
133 if (m->free_fds) {
134 close_many(m->fds, m->n_fds);
135 free(m->fds);
136 }
de1c301e 137
bc7fd8cd
LP
138 if (m->iovec != m->iovec_fixed)
139 free(m->iovec);
140
bc7fd8cd 141 message_reset_containers(m);
6d1e0f4f
ZJS
142 assert(m->n_containers == 0);
143 message_free_last_container(m);
d8d3d8a7 144
5b12334d 145 bus_creds_done(&m->creds);
2ab3a635 146 return mfree(m);
de1c301e
LP
147}
148
a452cfd7 149static void *message_extend_fields(sd_bus_message *m, size_t sz, bool add_offset) {
c91cb83c
LP
150 void *op, *np;
151 size_t old_size, new_size, start;
de1c301e 152
c91cb83c 153 assert(m);
35460afc
LP
154
155 if (m->poisoned)
156 return NULL;
de1c301e 157
2ac7c17f 158 old_size = sizeof(struct bus_header) + m->fields_size;
a452cfd7 159 start = ALIGN8(old_size);
c91cb83c 160 new_size = start + sz;
de1c301e 161
6f0647d5 162 if (new_size < start || new_size > UINT32_MAX)
2ac7c17f
LP
163 goto poison;
164
c91cb83c
LP
165 if (old_size == new_size)
166 return (uint8_t*) m->header + old_size;
de1c301e 167
c91cb83c
LP
168 if (m->free_header) {
169 np = realloc(m->header, ALIGN8(new_size));
170 if (!np)
171 goto poison;
172 } else {
61233823 173 /* Initially, the header is allocated as part of
c91cb83c
LP
174 * the sd_bus_message itself, let's replace it by
175 * dynamic data */
de1c301e 176
c91cb83c
LP
177 np = malloc(ALIGN8(new_size));
178 if (!np)
179 goto poison;
de1c301e 180
c91cb83c
LP
181 memcpy(np, m->header, sizeof(struct bus_header));
182 }
de1c301e 183
c91cb83c
LP
184 /* Zero out padding */
185 if (start > old_size)
29804cc1 186 memzero((uint8_t*) np + old_size, start - old_size);
bc7fd8cd 187
c91cb83c
LP
188 op = m->header;
189 m->header = np;
2ac7c17f 190 m->fields_size = new_size - sizeof(struct bus_header);
de1c301e 191
bc7fd8cd 192 /* Adjust quick access pointers */
c91cb83c
LP
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);
bc7fd8cd 199
c91cb83c 200 m->free_header = true;
de1c301e 201
c1b9d935
LP
202 if (add_offset) {
203 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
204 goto poison;
205
206 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
207 }
208
c91cb83c
LP
209 return (uint8_t*) np + start;
210
211poison:
212 m->poisoned = true;
213 return NULL;
de1c301e
LP
214}
215
216static int message_append_field_string(
217 sd_bus_message *m,
2ac7c17f 218 uint64_t h,
de1c301e
LP
219 char type,
220 const char *s,
221 const char **ret) {
222
223 size_t l;
224 uint8_t *p;
225
226 assert(m);
227
0dd48768 228 /* dbus only allows 8bit header field ids */
2ac7c17f
LP
229 if (h > 0xFF)
230 return -EINVAL;
231
0dd48768 232 /* dbus doesn't allow strings over 32bit */
de1c301e 233 l = strlen(s);
f22c308a 234 if (l > UINT32_MAX)
de1c301e
LP
235 return -EINVAL;
236
c1b9d935
LP
237 /* Signature "(yv)" where the variant contains "s" */
238
0dd48768 239 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
a452cfd7 240 p = message_extend_fields(m, 4 + 4 + l + 1, false);
0dd48768
YW
241 if (!p)
242 return -ENOMEM;
c1b9d935 243
0dd48768
YW
244 p[0] = (uint8_t) h;
245 p[1] = 1;
246 p[2] = type;
247 p[3] = 0;
c1b9d935 248
0dd48768
YW
249 ((uint32_t*) p)[1] = l;
250 memcpy(p + 8, s, l + 1);
c1b9d935 251
0dd48768
YW
252 if (ret)
253 *ret = (char*) p + 8;
de1c301e
LP
254
255 return 0;
256}
257
258static int message_append_field_signature(
259 sd_bus_message *m,
2ac7c17f 260 uint64_t h,
de1c301e
LP
261 const char *s,
262 const char **ret) {
263
264 size_t l;
265 uint8_t *p;
266
267 assert(m);
268
0dd48768 269 /* dbus only allows 8bit header field ids */
2ac7c17f
LP
270 if (h > 0xFF)
271 return -EINVAL;
272
0dd48768 273 /* dbus doesn't allow signatures over 8bit */
de1c301e 274 l = strlen(s);
cfcc0059 275 if (l > SD_BUS_MAXIMUM_SIGNATURE_LENGTH)
de1c301e
LP
276 return -EINVAL;
277
c1b9d935
LP
278 /* Signature "(yv)" where the variant contains "g" */
279
0dd48768 280 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
a452cfd7 281 p = message_extend_fields(m, 4 + 1 + l + 1, false);
0dd48768
YW
282 if (!p)
283 return -ENOMEM;
de1c301e 284
0dd48768
YW
285 p[0] = (uint8_t) h;
286 p[1] = 1;
287 p[2] = SD_BUS_TYPE_SIGNATURE;
288 p[3] = 0;
289 p[4] = l;
290 memcpy(p + 5, s, l + 1);
de1c301e 291
0dd48768
YW
292 if (ret)
293 *ret = (const char*) p + 5;
de1c301e
LP
294
295 return 0;
296}
297
2ac7c17f 298static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
de1c301e
LP
299 uint8_t *p;
300
301 assert(m);
302
0dd48768 303 /* dbus only allows 8bit header field ids */
2ac7c17f
LP
304 if (h > 0xFF)
305 return -EINVAL;
306
0dd48768 307 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
a452cfd7 308 p = message_extend_fields(m, 4 + 4, false);
0dd48768
YW
309 if (!p)
310 return -ENOMEM;
2ac7c17f 311
0dd48768
YW
312 p[0] = (uint8_t) h;
313 p[1] = 1;
314 p[2] = 'u';
315 p[3] = 0;
2ac7c17f 316
0dd48768 317 ((uint32_t*) p)[1] = x;
2ac7c17f
LP
318
319 return 0;
320}
321
b267a6d2
LP
322static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
323 assert(m);
324
0dd48768
YW
325 /* 64bit cookies are not supported */
326 if (cookie > UINT32_MAX)
327 return -EOPNOTSUPP;
b267a6d2 328
0dd48768 329 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
b267a6d2
LP
330}
331
75c85c3b 332static int message_from_header(
df2d202e 333 sd_bus *bus,
0dd48768 334 void *buffer,
2ac7c17f 335 size_t message_size,
2c93b4ef 336 int *fds,
da6053d0 337 size_t n_fds,
2571ead1
LP
338 const char *label,
339 sd_bus_message **ret) {
340
bcf88fc3 341 _cleanup_free_ sd_bus_message *m = NULL;
80a46c73 342 struct bus_header *h;
89b6a3f1 343 size_t a, label_sz = 0; /* avoid false maybe-uninitialized warning */
80a46c73 344
2a0958d2 345 assert(bus);
0dd48768 346 assert(buffer || message_size <= 0);
2c93b4ef 347 assert(fds || n_fds <= 0);
80a46c73
LP
348 assert(ret);
349
0dd48768 350 if (message_size < sizeof(struct bus_header))
80a46c73
LP
351 return -EBADMSG;
352
0dd48768 353 h = buffer;
bcf88fc3 354 if (!IN_SET(h->version, 1, 2))
954871d8
KS
355 return -EBADMSG;
356
a9c9f79e 357 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
80a46c73
LP
358 return -EBADMSG;
359
bcf88fc3 360 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
80a46c73
LP
361 return -EBADMSG;
362
2ac7c17f
LP
363 /* Note that we are happy with unknown flags in the flags header! */
364
0dd48768 365 a = ALIGN(sizeof(sd_bus_message));
80a46c73 366
2571ead1
LP
367 if (label) {
368 label_sz = strlen(label);
6629161f
LP
369 a += label_sz + 1;
370 }
2571ead1
LP
371
372 m = malloc0(a);
80a46c73
LP
373 if (!m)
374 return -ENOMEM;
375
2c93b4ef 376 m->sealed = true;
0dd48768 377 m->header = buffer;
2ac7c17f 378
0dd48768
YW
379 if (h->serial == 0)
380 return -EBADMSG;
2ac7c17f 381
0dd48768
YW
382 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->fields_size);
383 m->body_size = BUS_MESSAGE_BSWAP32(m, h->body_size);
2ac7c17f 384
0dd48768
YW
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))
388 return -EBADMSG;
2ac7c17f 389
2c93b4ef
LP
390 m->fds = fds;
391 m->n_fds = n_fds;
80a46c73 392
2571ead1 393 if (label) {
0dd48768 394 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message));
5b12334d
LP
395 memcpy(m->creds.label, label, label_sz + 1);
396
397 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
2571ead1
LP
398 }
399
e593b6a8 400 m->n_ref = 1;
2a0958d2 401 m->bus = sd_bus_ref(bus);
e593b6a8 402
1cc6c93a 403 *ret = TAKE_PTR(m);
2a0958d2 404
6629161f
LP
405 return 0;
406}
407
408int bus_message_from_malloc(
df2d202e 409 sd_bus *bus,
6629161f
LP
410 void *buffer,
411 size_t length,
412 int *fds,
da6053d0 413 size_t n_fds,
6629161f
LP
414 const char *label,
415 sd_bus_message **ret) {
416
b41812d1 417 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5461f53f 418 size_t sz;
6629161f
LP
419 int r;
420
75c85c3b 421 r = message_from_header(
2ac7c17f 422 bus,
2ac7c17f 423 buffer, length,
2ac7c17f 424 fds, n_fds,
aa0d0ed6 425 label,
0dd48768 426 &m);
6629161f
LP
427 if (r < 0)
428 return r;
429
2ac7c17f 430 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
5461f53f
LP
431 if (sz > 0) {
432 m->n_body_parts = 1;
2ac7c17f 433 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
5461f53f
LP
434 m->body.size = sz;
435 m->body.sealed = true;
436 m->body.memfd = -1;
437 }
6629161f 438
80a46c73 439 m->n_iovec = 1;
bc7fd8cd 440 m->iovec = m->iovec_fixed;
cb310866 441 m->iovec[0] = IOVEC_MAKE(buffer, length);
80a46c73 442
75c85c3b 443 r = message_parse_fields(m);
2c93b4ef 444 if (r < 0)
2ab3a635 445 return r;
2c93b4ef
LP
446
447 /* We take possession of the memory and fds now */
448 m->free_header = true;
449 m->free_fds = true;
80a46c73 450
2ab3a635 451 *ret = TAKE_PTR(m);
80a46c73
LP
452 return 0;
453}
454
75bcbcf2
SA
455_public_ int sd_bus_message_new(
456 sd_bus *bus,
457 sd_bus_message **m,
458 uint8_t type) {
de1c301e 459
75bcbcf2 460 assert_return(bus, -ENOTCONN);
501ecd67 461 assert_return(bus = bus_resolve(bus), -ENOPKG);
75bcbcf2
SA
462 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
463 assert_return(m, -EINVAL);
a9c9f79e
ZJS
464 /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
465 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
de1c301e 466
f41df695 467 sd_bus_message *t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
75bcbcf2
SA
468 if (!t)
469 return -ENOMEM;
470
471 t->n_ref = 1;
e593b6a8 472 t->bus = sd_bus_ref(bus);
75bcbcf2
SA
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);
9b05bc48 478
c0765ddb 479 if (bus->allow_interactive_authorization)
75bcbcf2 480 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
c0765ddb 481
75bcbcf2
SA
482 *m = t;
483 return 0;
de1c301e
LP
484}
485
d9f644e2 486_public_ int sd_bus_message_new_signal(
de1c301e 487 sd_bus *bus,
151b9b96 488 sd_bus_message **m,
de1c301e
LP
489 const char *path,
490 const char *interface,
151b9b96 491 const char *member) {
de1c301e 492
2ab3a635 493 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
de1c301e
LP
494 int r;
495
2a0958d2 496 assert_return(bus, -ENOTCONN);
501ecd67 497 assert_return(bus = bus_resolve(bus), -ENOPKG);
2a0958d2 498 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
9d6c7c82
LP
499 assert_return(object_path_is_valid(path), -EINVAL);
500 assert_return(interface_name_is_valid(interface), -EINVAL);
501 assert_return(member_name_is_valid(member), -EINVAL);
502 assert_return(m, -EINVAL);
de1c301e 503
75bcbcf2
SA
504 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
505 if (r < 0)
de1c301e
LP
506 return -ENOMEM;
507
75bcbcf2
SA
508 assert(t);
509
0461f8cd 510 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
89ffcd2a 511
0461f8cd 512 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
de1c301e 513 if (r < 0)
2ab3a635 514 return r;
0461f8cd 515 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
de1c301e 516 if (r < 0)
2ab3a635 517 return r;
0461f8cd 518 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
de1c301e 519 if (r < 0)
2ab3a635 520 return r;
de1c301e 521
2ab3a635 522 *m = TAKE_PTR(t);
de1c301e 523 return 0;
de1c301e
LP
524}
525
d9f644e2 526_public_ int sd_bus_message_new_method_call(
de1c301e 527 sd_bus *bus,
151b9b96 528 sd_bus_message **m,
de1c301e
LP
529 const char *destination,
530 const char *path,
531 const char *interface,
151b9b96 532 const char *member) {
de1c301e 533
b41812d1 534 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
de1c301e
LP
535 int r;
536
2a0958d2 537 assert_return(bus, -ENOTCONN);
501ecd67 538 assert_return(bus = bus_resolve(bus), -ENOPKG);
2a0958d2 539 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
9d6c7c82
LP
540 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
541 assert_return(object_path_is_valid(path), -EINVAL);
542 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
543 assert_return(member_name_is_valid(member), -EINVAL);
544 assert_return(m, -EINVAL);
de1c301e 545
75bcbcf2
SA
546 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
547 if (r < 0)
de1c301e
LP
548 return -ENOMEM;
549
75bcbcf2
SA
550 assert(t);
551
0461f8cd 552 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
de1c301e 553 if (r < 0)
2ab3a635 554 return r;
0461f8cd 555 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
de1c301e 556 if (r < 0)
2ab3a635 557 return r;
de1c301e
LP
558
559 if (interface) {
0461f8cd 560 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
de1c301e 561 if (r < 0)
2ab3a635 562 return r;
de1c301e
LP
563 }
564
565 if (destination) {
0461f8cd 566 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
de1c301e 567 if (r < 0)
2ab3a635 568 return r;
de1c301e
LP
569 }
570
2ab3a635 571 *m = TAKE_PTR(t);
de1c301e 572 return 0;
de1c301e
LP
573}
574
5407f2de 575static int message_new_reply(
de1c301e 576 sd_bus_message *call,
5407f2de 577 uint8_t type,
de1c301e
LP
578 sd_bus_message **m) {
579
b41812d1 580 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
f581267a 581 uint64_t cookie;
de1c301e
LP
582 int r;
583
9d6c7c82
LP
584 assert_return(call, -EINVAL);
585 assert_return(call->sealed, -EPERM);
586 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
2a0958d2 587 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
9d6c7c82 588 assert_return(m, -EINVAL);
de1c301e 589
f581267a
CW
590 cookie = BUS_MESSAGE_COOKIE(call);
591 if (cookie == 0)
592 return -EOPNOTSUPP;
593
75bcbcf2
SA
594 r = sd_bus_message_new(call->bus, &t, type);
595 if (r < 0)
de1c301e
LP
596 return -ENOMEM;
597
75bcbcf2
SA
598 assert(t);
599
0461f8cd 600 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
f581267a 601 t->reply_cookie = cookie;
b267a6d2 602 r = message_append_reply_cookie(t, t->reply_cookie);
de1c301e 603 if (r < 0)
2ab3a635 604 return r;
de1c301e
LP
605
606 if (call->sender) {
0461f8cd 607 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
de1c301e 608 if (r < 0)
2ab3a635 609 return r;
de1c301e
LP
610 }
611
0461f8cd 612 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
6717d473 613 t->enforced_reply_signature = call->enforced_reply_signature;
5407f2de 614
7a77d2a4
LP
615 /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
616 * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
617 * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
618 * to both the message call and the reply. */
619 t->sensitive = call->sensitive;
620
2ab3a635 621 *m = TAKE_PTR(t);
89ffcd2a 622 return 0;
de1c301e
LP
623}
624
d9f644e2 625_public_ int sd_bus_message_new_method_return(
5407f2de
LP
626 sd_bus_message *call,
627 sd_bus_message **m) {
628
df2d202e 629 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
5407f2de
LP
630}
631
d9f644e2 632_public_ int sd_bus_message_new_method_error(
de1c301e 633 sd_bus_message *call,
151b9b96
LP
634 sd_bus_message **m,
635 const sd_bus_error *e) {
de1c301e 636
b41812d1 637 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
de1c301e
LP
638 int r;
639
9d6c7c82
LP
640 assert_return(sd_bus_error_is_set(e), -EINVAL);
641 assert_return(m, -EINVAL);
de1c301e 642
df2d202e 643 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
de1c301e 644 if (r < 0)
5407f2de 645 return r;
de1c301e 646
0461f8cd 647 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
de1c301e 648 if (r < 0)
2ab3a635 649 return r;
de1c301e
LP
650
651 if (e->message) {
652 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
653 if (r < 0)
2ab3a635 654 return r;
de1c301e
LP
655 }
656
79f8d3d2
LP
657 t->error._need_free = -1;
658
2ab3a635 659 *m = TAKE_PTR(t);
de1c301e 660 return 0;
de1c301e
LP
661}
662
d9f644e2 663_public_ int sd_bus_message_new_method_errorf(
29ddb38f
LP
664 sd_bus_message *call,
665 sd_bus_message **m,
666 const char *name,
667 const char *format,
668 ...) {
669
4afd3348 670 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
29ddb38f 671 va_list ap;
29ddb38f 672
40ca29a1
LP
673 assert_return(name, -EINVAL);
674 assert_return(m, -EINVAL);
675
676 va_start(ap, format);
fc69fab5 677 sd_bus_error_setfv(&error, name, format, ap);
40ca29a1 678 va_end(ap);
29ddb38f 679
151b9b96 680 return sd_bus_message_new_method_error(call, m, &error);
40ca29a1 681}
29ddb38f 682
d9f644e2 683_public_ int sd_bus_message_new_method_errno(
40ca29a1 684 sd_bus_message *call,
151b9b96 685 sd_bus_message **m,
40ca29a1 686 int error,
151b9b96 687 const sd_bus_error *p) {
29ddb38f 688
4afd3348 689 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
29ddb38f 690
40ca29a1 691 if (sd_bus_error_is_set(p))
151b9b96 692 return sd_bus_message_new_method_error(call, m, p);
29ddb38f 693
40ca29a1 694 sd_bus_error_set_errno(&berror, error);
29ddb38f 695
151b9b96 696 return sd_bus_message_new_method_error(call, m, &berror);
40ca29a1 697}
29ddb38f 698
d9f644e2 699_public_ int sd_bus_message_new_method_errnof(
40ca29a1
LP
700 sd_bus_message *call,
701 sd_bus_message **m,
702 int error,
703 const char *format,
704 ...) {
705
4afd3348 706 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
40ca29a1 707 va_list ap;
40ca29a1
LP
708
709 va_start(ap, format);
07a0d22f 710 sd_bus_error_set_errnofv(&berror, error, format, ap);
40ca29a1
LP
711 va_end(ap);
712
151b9b96 713 return sd_bus_message_new_method_error(call, m, &berror);
29ddb38f
LP
714}
715
d29ae291
LP
716void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
717 assert(bus);
718 assert(m);
719
720 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
721 m->creds.well_known_names_local = true;
722 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
723}
724
725void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
726 assert(bus);
727 assert(m);
728
729 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
730 m->creds.well_known_names_driver = true;
731 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
732}
733
eb01ba5d
LP
734int bus_message_new_synthetic_error(
735 sd_bus *bus,
693eb9a2 736 uint64_t cookie,
eb01ba5d
LP
737 const sd_bus_error *e,
738 sd_bus_message **m) {
739
b41812d1 740 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
eb01ba5d
LP
741 int r;
742
2a0958d2 743 assert(bus);
eb01ba5d
LP
744 assert(sd_bus_error_is_set(e));
745 assert(m);
746
75bcbcf2
SA
747 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
748 if (r < 0)
eb01ba5d
LP
749 return -ENOMEM;
750
75bcbcf2
SA
751 assert(t);
752
0461f8cd 753 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
693eb9a2 754 t->reply_cookie = cookie;
eb01ba5d 755
b267a6d2 756 r = message_append_reply_cookie(t, t->reply_cookie);
eb01ba5d 757 if (r < 0)
2ab3a635 758 return r;
eb01ba5d
LP
759
760 if (bus && bus->unique_name) {
0461f8cd 761 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
eb01ba5d 762 if (r < 0)
2ab3a635 763 return r;
eb01ba5d
LP
764 }
765
0461f8cd 766 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
3a7d4f1b 767 if (r < 0)
2ab3a635 768 return r;
3a7d4f1b
LP
769
770 if (e->message) {
771 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
772 if (r < 0)
2ab3a635 773 return r;
3a7d4f1b
LP
774 }
775
79f8d3d2
LP
776 t->error._need_free = -1;
777
d29ae291
LP
778 bus_message_set_sender_driver(bus, t);
779
2ab3a635 780 *m = TAKE_PTR(t);
eb01ba5d 781 return 0;
eb01ba5d
LP
782}
783
1b3f9dd7
LP
784_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
785 if (!m)
786 return NULL;
787
788 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
789 * least one bus connection object. */
790 assert(m->n_ref > 0 || m->n_queued > 0);
791
792 m->n_ref++;
793
794 /* Each user reference to a bus message shall also be considered a ref on the bus */
795 sd_bus_ref(m->bus);
796 return m;
797}
798
799_public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
800 if (!m)
801 return NULL;
802
803 assert(m->n_ref > 0);
804
805 sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
806 * here. Note we have to do this before decrementing our own n_ref here, since
807 * otherwise, if this message is currently queued sd_bus_unref() might call
808 * bus_message_unref_queued() for this which might then destroy the message
809 * while we are still processing it. */
810 m->n_ref--;
811
812 if (m->n_ref > 0 || m->n_queued > 0)
813 return NULL;
814
815 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
816 * to reset the field only after the last reference to the bus is dropped, after all we might keep
5238e957 817 * multiple references to the bus, once for each reference kept on ourselves. */
1b3f9dd7
LP
818 m->bus = NULL;
819
820 return message_free(m);
821}
822
823sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) {
824 if (!m)
825 return NULL;
826
827 /* If this is a different bus than the message is associated with, then implicitly turn this into a
828 * regular reference. This means that you can create a memory leak by enqueuing a message generated
829 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
830 * as we'll not detect the cyclic references there. */
831 if (bus != m->bus)
832 return sd_bus_message_ref(m);
833
834 assert(m->n_ref > 0 || m->n_queued > 0);
835 m->n_queued++;
836
837 return m;
838}
839
840sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) {
841 if (!m)
842 return NULL;
843
844 if (bus != m->bus)
845 return sd_bus_message_unref(m);
846
847 assert(m->n_queued > 0);
848 m->n_queued--;
849
850 if (m->n_ref > 0 || m->n_queued > 0)
851 return NULL;
852
853 m->bus = NULL;
854
855 return message_free(m);
856}
de1c301e 857
d9f644e2 858_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
9d6c7c82
LP
859 assert_return(m, -EINVAL);
860 assert_return(type, -EINVAL);
de1c301e
LP
861
862 *type = m->header->type;
863 return 0;
864}
865
693eb9a2 866_public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
2ac7c17f
LP
867 uint64_t c;
868
9d6c7c82 869 assert_return(m, -EINVAL);
693eb9a2 870 assert_return(cookie, -EINVAL);
2ac7c17f
LP
871
872 c = BUS_MESSAGE_COOKIE(m);
873 if (c == 0)
874 return -ENODATA;
de1c301e 875
693eb9a2 876 *cookie = BUS_MESSAGE_COOKIE(m);
de1c301e
LP
877 return 0;
878}
879
693eb9a2 880_public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
9d6c7c82 881 assert_return(m, -EINVAL);
693eb9a2 882 assert_return(cookie, -EINVAL);
2ac7c17f
LP
883
884 if (m->reply_cookie == 0)
885 return -ENODATA;
de1c301e 886
693eb9a2 887 *cookie = m->reply_cookie;
de1c301e
LP
888 return 0;
889}
890
eee9ec0e 891_public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
9d6c7c82 892 assert_return(m, -EINVAL);
de1c301e 893
eee9ec0e
LP
894 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
895 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
de1c301e
LP
896}
897
eee9ec0e 898_public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
1fee9de5
LP
899 assert_return(m, -EINVAL);
900
eee9ec0e 901 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1fee9de5
LP
902}
903
53a83f4b
LP
904_public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
905 assert_return(m, -EINVAL);
906
907 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
908 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
909}
910
d9f644e2 911_public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
9d6c7c82 912 assert_return(m, NULL);
de1c301e
LP
913
914 return m->path;
915}
916
d9f644e2 917_public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
9d6c7c82 918 assert_return(m, NULL);
de1c301e
LP
919
920 return m->interface;
921}
922
d9f644e2 923_public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
9d6c7c82 924 assert_return(m, NULL);
de1c301e
LP
925
926 return m->member;
927}
d9f644e2
ZJS
928
929_public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
9d6c7c82 930 assert_return(m, NULL);
de1c301e
LP
931
932 return m->destination;
933}
934
d9f644e2 935_public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
9d6c7c82 936 assert_return(m, NULL);
de1c301e
LP
937
938 return m->sender;
939}
940
d9f644e2 941_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
9d6c7c82 942 assert_return(m, NULL);
f02b9615
LP
943
944 if (!sd_bus_error_is_set(&m->error))
945 return NULL;
de1c301e
LP
946
947 return &m->error;
948}
949
1fedcf59 950_public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
9d6c7c82
LP
951 assert_return(m, -EINVAL);
952 assert_return(usec, -EINVAL);
1fedcf59
LP
953
954 if (m->monotonic <= 0)
955 return -ENODATA;
acb5a3cb 956
69aec65c 957 *usec = m->monotonic;
acb5a3cb
LP
958 return 0;
959}
960
1fedcf59 961_public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
9d6c7c82
LP
962 assert_return(m, -EINVAL);
963 assert_return(usec, -EINVAL);
1fedcf59
LP
964
965 if (m->realtime <= 0)
966 return -ENODATA;
69aec65c
LP
967
968 *usec = m->realtime;
969 return 0;
970}
971
6a0e376c
LP
972_public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
973 assert_return(m, -EINVAL);
974 assert_return(seqnum, -EINVAL);
1fedcf59
LP
975
976 if (m->seqnum <= 0)
977 return -ENODATA;
6a0e376c
LP
978
979 *seqnum = m->seqnum;
980 return 0;
981}
982
5b12334d
LP
983_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
984 assert_return(m, NULL);
102ea8e4 985
5b12334d
LP
986 if (m->creds.mask == 0)
987 return NULL;
102ea8e4 988
5b12334d 989 return &m->creds;
102ea8e4
LP
990}
991
2ac7c17f
LP
992_public_ int sd_bus_message_is_signal(
993 sd_bus_message *m,
994 const char *interface,
995 const char *member) {
996
9d6c7c82 997 assert_return(m, -EINVAL);
de1c301e 998
40ca29a1 999 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
de1c301e
LP
1000 return 0;
1001
162c8755 1002 if (interface && !streq_ptr(m->interface, interface))
de1c301e
LP
1003 return 0;
1004
162c8755 1005 if (member && !streq_ptr(m->member, member))
de1c301e
LP
1006 return 0;
1007
1008 return 1;
1009}
1010
2ac7c17f
LP
1011_public_ int sd_bus_message_is_method_call(
1012 sd_bus_message *m,
1013 const char *interface,
1014 const char *member) {
1015
9d6c7c82 1016 assert_return(m, -EINVAL);
de1c301e 1017
40ca29a1 1018 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
de1c301e
LP
1019 return 0;
1020
162c8755 1021 if (interface && !streq_ptr(m->interface, interface))
de1c301e
LP
1022 return 0;
1023
162c8755 1024 if (member && !streq_ptr(m->member, member))
de1c301e
LP
1025 return 0;
1026
1027 return 1;
1028}
1029
d9f644e2 1030_public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
9d6c7c82 1031 assert_return(m, -EINVAL);
de1c301e 1032
40ca29a1 1033 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
de1c301e
LP
1034 return 0;
1035
162c8755 1036 if (name && !streq_ptr(m->error.name, name))
de1c301e
LP
1037 return 0;
1038
1039 return 1;
1040}
1041
eee9ec0e 1042_public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
9d6c7c82
LP
1043 assert_return(m, -EINVAL);
1044 assert_return(!m->sealed, -EPERM);
1045 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
de1c301e 1046
5883ff60 1047 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
de1c301e
LP
1048
1049 return 0;
1050}
1051
eee9ec0e 1052_public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1fee9de5
LP
1053 assert_return(m, -EINVAL);
1054 assert_return(!m->sealed, -EPERM);
1055
5883ff60 1056 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1fee9de5
LP
1057
1058 return 0;
1059}
1060
53a83f4b
LP
1061_public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1062 assert_return(m, -EINVAL);
1063 assert_return(!m->sealed, -EPERM);
1064
5883ff60 1065 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
53a83f4b
LP
1066
1067 return 0;
1068}
1069
75c85c3b 1070static struct bus_body_part *message_append_part(sd_bus_message *m) {
bc7fd8cd
LP
1071 struct bus_body_part *part;
1072
1073 assert(m);
35460afc
LP
1074
1075 if (m->poisoned)
1076 return NULL;
bc7fd8cd
LP
1077
1078 if (m->n_body_parts <= 0) {
1079 part = &m->body;
1080 zero(*part);
1081 } else {
1082 assert(m->body_end);
1083
1084 part = new0(struct bus_body_part, 1);
1085 if (!part) {
1086 m->poisoned = true;
1087 return NULL;
1088 }
1089
1090 m->body_end->next = part;
1091 }
1092
1093 part->memfd = -1;
1094 m->body_end = part;
313cefa1 1095 m->n_body_parts++;
bc7fd8cd
LP
1096
1097 return part;
1098}
1099
1100static void part_zero(struct bus_body_part *part, size_t sz) {
1101 assert(part);
1102 assert(sz > 0);
1103 assert(sz < 8);
1104
453a0c29
LP
1105 /* All other fields can be left in their defaults */
1106 assert(!part->data);
1107 assert(part->memfd < 0);
1108
bc7fd8cd 1109 part->size = sz;
453a0c29
LP
1110 part->is_zero = true;
1111 part->sealed = true;
bc7fd8cd
LP
1112}
1113
1114static int part_make_space(
1115 struct sd_bus_message *m,
1116 struct bus_body_part *part,
1117 size_t sz,
1118 void **q) {
1119
1120 void *n;
bc7fd8cd
LP
1121
1122 assert(m);
1123 assert(part);
1124 assert(!part->sealed);
1125
1126 if (m->poisoned)
1127 return -ENOMEM;
1128
a132bef0
ZJS
1129 if (part->allocated == 0 || sz > part->allocated) {
1130 size_t new_allocated;
bc7fd8cd 1131
a132bef0
ZJS
1132 new_allocated = sz > 0 ? 2 * sz : 64;
1133 n = realloc(part->data, new_allocated);
1134 if (!n) {
1135 m->poisoned = true;
1136 return -ENOMEM;
bc7fd8cd 1137 }
bf30e48f 1138
a132bef0
ZJS
1139 part->data = n;
1140 part->allocated = new_allocated;
1141 part->free_this = true;
bc7fd8cd
LP
1142 }
1143
1144 if (q)
1145 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1146
1147 part->size = sz;
1148 return 0;
1149}
1150
453a0c29 1151static void message_extend_containers(sd_bus_message *m, size_t expand) {
453a0c29
LP
1152 assert(m);
1153
1154 if (expand <= 0)
1155 return;
1156
0cd41757
LP
1157 if (m->n_containers <= 0)
1158 return;
c1b9d935 1159
0cd41757
LP
1160 /* Update counters */
1161 for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++)
453a0c29
LP
1162 if (c->array_size)
1163 *c->array_size += expand;
453a0c29
LP
1164}
1165
2ac7c17f
LP
1166static void *message_extend_body(
1167 sd_bus_message *m,
1168 size_t align,
0dd48768 1169 size_t sz) {
2ac7c17f 1170
f3097697 1171 size_t start_body, end_body, padding, added;
bc7fd8cd
LP
1172 void *p;
1173 int r;
de1c301e
LP
1174
1175 assert(m);
9a17484d 1176 assert(align > 0);
bc7fd8cd 1177 assert(!m->sealed);
35460afc
LP
1178
1179 if (m->poisoned)
1180 return NULL;
de1c301e 1181
b7096bd6 1182 start_body = ALIGN_TO(m->body_size, align);
bc7fd8cd
LP
1183 end_body = start_body + sz;
1184
2ac7c17f 1185 padding = start_body - m->body_size;
bc7fd8cd
LP
1186 added = padding + sz;
1187
1188 /* Check for 32bit overflows */
6f0647d5 1189 if (end_body < start_body || end_body > UINT32_MAX) {
bc7fd8cd 1190 m->poisoned = true;
de1c301e 1191 return NULL;
bc7fd8cd 1192 }
de1c301e 1193
f3097697
LP
1194 if (added > 0) {
1195 struct bus_body_part *part = NULL;
1196 bool add_new_part;
1197
1198 add_new_part =
1199 m->n_body_parts <= 0 ||
1200 m->body_end->sealed ||
0dd48768 1201 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size);
0241c1c0
ZJS
1202 /* If this must be an inlined extension, let's create a new part if
1203 * the previous part is large enough to be inlined. */
f3097697
LP
1204
1205 if (add_new_part) {
1206 if (padding > 0) {
1207 part = message_append_part(m);
1208 if (!part)
1209 return NULL;
1210
1211 part_zero(part, padding);
1212 }
de1c301e 1213
bc7fd8cd
LP
1214 part = message_append_part(m);
1215 if (!part)
1216 return NULL;
1217
f3097697
LP
1218 r = part_make_space(m, part, sz, &p);
1219 if (r < 0)
1220 return NULL;
1221 } else {
f3097697
LP
1222 void *op;
1223 size_t os, start_part, end_part;
bc7fd8cd 1224
f3097697
LP
1225 part = m->body_end;
1226 op = part->data;
1227 os = part->size;
bc7fd8cd 1228
f3097697
LP
1229 start_part = ALIGN_TO(part->size, align);
1230 end_part = start_part + sz;
bc7fd8cd 1231
f3097697
LP
1232 r = part_make_space(m, part, end_part, &p);
1233 if (r < 0)
1234 return NULL;
bc7fd8cd 1235
f3097697 1236 if (padding > 0) {
29804cc1 1237 memzero(p, padding);
f3097697
LP
1238 p = (uint8_t*) p + padding;
1239 }
bc7fd8cd 1240
f3097697 1241 /* Readjust pointers */
0cd41757
LP
1242 if (m->n_containers > 0)
1243 for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++)
1244 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
bc7fd8cd 1245
f3097697 1246 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
de1c301e 1247 }
f3097697
LP
1248 } else
1249 /* Return something that is not NULL and is aligned */
0241c1c0 1250 p = (uint8_t*) align;
de1c301e 1251
2ac7c17f 1252 m->body_size = end_body;
453a0c29 1253 message_extend_containers(m, added);
de1c301e
LP
1254
1255 return p;
1256}
1257
c1b9d935
LP
1258static int message_push_fd(sd_bus_message *m, int fd) {
1259 int *f, copy;
1260
1261 assert(m);
1262
1263 if (fd < 0)
1264 return -EINVAL;
1265
1266 if (!m->allow_fds)
15411c0c 1267 return -EOPNOTSUPP;
c1b9d935
LP
1268
1269 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1270 if (copy < 0)
1271 return -errno;
1272
62d74c78 1273 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
c1b9d935
LP
1274 if (!f) {
1275 m->poisoned = true;
03e334a1 1276 safe_close(copy);
c1b9d935
LP
1277 return -ENOMEM;
1278 }
1279
1280 m->fds = f;
1281 m->fds[m->n_fds] = copy;
1282 m->free_fds = true;
1283
1284 return copy;
1285}
1286
de1c301e 1287int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
c1b9d935 1288 _cleanup_close_ int fd = -1;
de1c301e 1289 struct bus_container *c;
27f6e5c7 1290 ssize_t align, sz;
0dd48768 1291 uint32_t u32;
de1c301e 1292 void *a;
de1c301e 1293
9d6c7c82 1294 assert_return(m, -EINVAL);
9d6c7c82
LP
1295 assert_return(!m->sealed, -EPERM);
1296 assert_return(bus_type_is_basic(type), -EINVAL);
1297 assert_return(!m->poisoned, -ESTALE);
de1c301e 1298
9c65778d 1299 c = message_get_last_container(m);
de1c301e
LP
1300
1301 if (c->signature && c->signature[c->index]) {
1302 /* Container signature is already set */
1303
1304 if (c->signature[c->index] != type)
9a17484d 1305 return -ENXIO;
de1c301e 1306 } else {
5cbe7492
LP
1307 char *e;
1308
ad67ef27 1309 /* Maybe we can append to the signature? But only if this is the top-level container */
de1c301e 1310 if (c->enclosing != 0)
9a17484d 1311 return -ENXIO;
de1c301e 1312
c2bc710b 1313 e = strextend(&c->signature, CHAR_TO_STR(type));
bc7fd8cd
LP
1314 if (!e) {
1315 m->poisoned = true;
de1c301e 1316 return -ENOMEM;
bc7fd8cd 1317 }
de1c301e
LP
1318 }
1319
0dd48768 1320 switch (type) {
2c93b4ef 1321
0dd48768
YW
1322 case SD_BUS_TYPE_STRING:
1323 /* To make things easy we'll serialize a NULL string
1324 * into the empty string */
1325 p = strempty(p);
b3273daf 1326
0dd48768
YW
1327 _fallthrough_;
1328 case SD_BUS_TYPE_OBJECT_PATH:
de1c301e 1329
0dd48768
YW
1330 if (!p)
1331 return -EINVAL;
de1c301e 1332
0dd48768
YW
1333 align = 4;
1334 sz = 4 + strlen(p) + 1;
1335 break;
de1c301e 1336
0dd48768 1337 case SD_BUS_TYPE_SIGNATURE:
de1c301e 1338
0dd48768 1339 p = strempty(p);
de1c301e 1340
0dd48768
YW
1341 align = 1;
1342 sz = 1 + strlen(p) + 1;
1343 break;
de1c301e 1344
0dd48768 1345 case SD_BUS_TYPE_BOOLEAN:
2c93b4ef 1346
0dd48768
YW
1347 u32 = p && *(int*) p;
1348 p = &u32;
6647dc66 1349
0dd48768
YW
1350 align = sz = 4;
1351 break;
2c93b4ef 1352
0dd48768 1353 case SD_BUS_TYPE_UNIX_FD:
de1c301e 1354
0dd48768
YW
1355 if (!p)
1356 return -EINVAL;
de1c301e 1357
0dd48768
YW
1358 fd = message_push_fd(m, *(int*) p);
1359 if (fd < 0)
1360 return fd;
c1b9d935 1361
0dd48768
YW
1362 u32 = m->n_fds;
1363 p = &u32;
c1b9d935 1364
0dd48768
YW
1365 align = sz = 4;
1366 break;
c1b9d935 1367
0dd48768
YW
1368 default:
1369 align = bus_type_get_alignment(type);
1370 sz = bus_type_get_size(type);
1371 break;
1372 }
c1b9d935 1373
0dd48768
YW
1374 assert(align > 0);
1375 assert(sz > 0);
c1b9d935 1376
0dd48768
YW
1377 a = message_extend_body(m, align, sz);
1378 if (!a)
1379 return -ENOMEM;
c1b9d935 1380
0dd48768
YW
1381 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1382 *(uint32_t*) a = sz - 5;
1383 memcpy((uint8_t*) a + 4, p, sz - 4);
c1b9d935 1384
0dd48768
YW
1385 if (stored)
1386 *stored = (const uint8_t*) a + 4;
c1b9d935 1387
0dd48768
YW
1388 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1389 *(uint8_t*) a = sz - 2;
1390 memcpy((uint8_t*) a + 1, p, sz - 1);
c1b9d935 1391
0dd48768
YW
1392 if (stored)
1393 *stored = (const uint8_t*) a + 1;
1394 } else {
1395 memcpy(a, p, sz);
c1b9d935 1396
0dd48768
YW
1397 if (stored)
1398 *stored = a;
de1c301e
LP
1399 }
1400
c1b9d935 1401 if (type == SD_BUS_TYPE_UNIX_FD)
313cefa1 1402 m->n_fds++;
c1b9d935 1403
de1c301e 1404 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1405 c->index++;
de1c301e 1406
c1b9d935 1407 fd = -1;
de1c301e
LP
1408 return 0;
1409}
1410
d9f644e2 1411_public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
de1c301e
LP
1412 return message_append_basic(m, type, p, NULL);
1413}
1414
938bcbab
LP
1415_public_ int sd_bus_message_append_string_space(
1416 sd_bus_message *m,
1417 size_t size,
1418 char **s) {
1419
f8e013f8 1420 struct bus_container *c;
f8e013f8 1421 void *a;
f8e013f8 1422
9d6c7c82
LP
1423 assert_return(m, -EINVAL);
1424 assert_return(s, -EINVAL);
1425 assert_return(!m->sealed, -EPERM);
1426 assert_return(!m->poisoned, -ESTALE);
f8e013f8 1427
9c65778d 1428 c = message_get_last_container(m);
f8e013f8
LP
1429
1430 if (c->signature && c->signature[c->index]) {
1431 /* Container signature is already set */
1432
1433 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1434 return -ENXIO;
1435 } else {
5cbe7492
LP
1436 char *e;
1437
ad67ef27 1438 /* Maybe we can append to the signature? But only if this is the top-level container */
f8e013f8
LP
1439 if (c->enclosing != 0)
1440 return -ENXIO;
1441
c2bc710b 1442 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING));
bc7fd8cd
LP
1443 if (!e) {
1444 m->poisoned = true;
f8e013f8 1445 return -ENOMEM;
bc7fd8cd 1446 }
f8e013f8
LP
1447 }
1448
0dd48768
YW
1449 a = message_extend_body(m, 4, 4 + size + 1);
1450 if (!a)
1451 return -ENOMEM;
f8e013f8 1452
0dd48768
YW
1453 *(uint32_t*) a = size;
1454 *s = (char*) a + 4;
f8e013f8
LP
1455
1456 (*s)[size] = 0;
1457
1458 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1459 c->index++;
1460
1461 return 0;
f8e013f8
LP
1462}
1463
938bcbab
LP
1464_public_ int sd_bus_message_append_string_iovec(
1465 sd_bus_message *m,
1466 const struct iovec *iov,
da6053d0 1467 unsigned n /* should be size_t, but is API now… 😞 */) {
938bcbab
LP
1468
1469 size_t size;
1470 unsigned i;
1471 char *p;
1472 int r;
1473
1474 assert_return(m, -EINVAL);
1475 assert_return(!m->sealed, -EPERM);
1476 assert_return(iov || n == 0, -EINVAL);
1477 assert_return(!m->poisoned, -ESTALE);
1478
1479 size = IOVEC_TOTAL_SIZE(iov, n);
1480
1481 r = sd_bus_message_append_string_space(m, size, &p);
1482 if (r < 0)
1483 return r;
1484
1485 for (i = 0; i < n; i++) {
1486
1487 if (iov[i].iov_base)
1488 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1489 else
1490 memset(p, ' ', iov[i].iov_len);
1491
1492 p += iov[i].iov_len;
1493 }
1494
1495 return 0;
1496}
1497
de1c301e
LP
1498static int bus_message_open_array(
1499 sd_bus_message *m,
1500 struct bus_container *c,
1501 const char *contents,
c1b9d935 1502 uint32_t **array_size,
0dd48768 1503 size_t *begin) {
de1c301e 1504
9a17484d 1505 unsigned nindex;
0dd48768
YW
1506 int alignment;
1507 void *a, *op;
1508 size_t os;
1509 struct bus_body_part *o;
de1c301e
LP
1510
1511 assert(m);
1512 assert(c);
1513 assert(contents);
1514 assert(array_size);
c1b9d935 1515 assert(begin);
de1c301e 1516
29ddb38f 1517 if (!signature_is_single(contents, true))
de1c301e
LP
1518 return -EINVAL;
1519
de1c301e
LP
1520 if (c->signature && c->signature[c->index]) {
1521
1522 /* Verify the existing signature */
1523
1524 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 1525 return -ENXIO;
de1c301e
LP
1526
1527 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 1528 return -ENXIO;
de1c301e
LP
1529
1530 nindex = c->index + 1 + strlen(contents);
1531 } else {
5cbe7492
LP
1532 char *e;
1533
de1c301e 1534 if (c->enclosing != 0)
9a17484d 1535 return -ENXIO;
de1c301e
LP
1536
1537 /* Extend the existing signature */
1538
c2bc710b 1539 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents);
bc7fd8cd
LP
1540 if (!e) {
1541 m->poisoned = true;
de1c301e 1542 return -ENOMEM;
bc7fd8cd 1543 }
de1c301e
LP
1544
1545 nindex = e - c->signature;
1546 }
1547
0dd48768
YW
1548 alignment = bus_type_get_alignment(contents[0]);
1549 if (alignment < 0)
1550 return alignment;
c1b9d935 1551
0dd48768
YW
1552 a = message_extend_body(m, 4, 4);
1553 if (!a)
1554 return -ENOMEM;
c1b9d935 1555
0dd48768
YW
1556 o = m->body_end;
1557 op = m->body_end->data;
1558 os = m->body_end->size;
c1b9d935 1559
0dd48768
YW
1560 /* Add alignment between size and first element */
1561 if (!message_extend_body(m, alignment, 0))
1562 return -ENOMEM;
c1b9d935 1563
0dd48768
YW
1564 /* location of array size might have changed so let's readjust a */
1565 if (o == m->body_end)
1566 a = adjust_pointer(a, op, os, m->body_end->data);
c1b9d935 1567
0dd48768
YW
1568 *(uint32_t*) a = 0;
1569 *array_size = a;
de1c301e
LP
1570
1571 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1572 c->index = nindex;
1573
de1c301e
LP
1574 return 0;
1575}
1576
1577static int bus_message_open_variant(
1578 sd_bus_message *m,
1579 struct bus_container *c,
1580 const char *contents) {
1581
0dd48768
YW
1582 size_t l;
1583 void *a;
1584
de1c301e
LP
1585 assert(m);
1586 assert(c);
1587 assert(contents);
1588
29ddb38f 1589 if (!signature_is_single(contents, false))
de1c301e
LP
1590 return -EINVAL;
1591
1592 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1593 return -EINVAL;
1594
1595 if (c->signature && c->signature[c->index]) {
1596
1597 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1598 return -ENXIO;
de1c301e
LP
1599
1600 } else {
5cbe7492
LP
1601 char *e;
1602
de1c301e 1603 if (c->enclosing != 0)
9a17484d 1604 return -ENXIO;
de1c301e 1605
c2bc710b 1606 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT));
bc7fd8cd
LP
1607 if (!e) {
1608 m->poisoned = true;
de1c301e 1609 return -ENOMEM;
bc7fd8cd 1610 }
de1c301e
LP
1611 }
1612
0dd48768
YW
1613 l = strlen(contents);
1614 a = message_extend_body(m, 1, 1 + l + 1);
1615 if (!a)
1616 return -ENOMEM;
c1b9d935 1617
0dd48768
YW
1618 *(uint8_t*) a = l;
1619 memcpy((uint8_t*) a + 1, contents, l + 1);
de1c301e
LP
1620
1621 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1622 c->index++;
de1c301e
LP
1623
1624 return 0;
1625}
1626
1627static int bus_message_open_struct(
1628 sd_bus_message *m,
1629 struct bus_container *c,
c1b9d935 1630 const char *contents,
0dd48768 1631 size_t *begin) {
de1c301e
LP
1632
1633 size_t nindex;
de1c301e
LP
1634
1635 assert(m);
1636 assert(c);
1637 assert(contents);
c1b9d935 1638 assert(begin);
de1c301e
LP
1639
1640 if (!signature_is_valid(contents, false))
1641 return -EINVAL;
1642
1643 if (c->signature && c->signature[c->index]) {
1644 size_t l;
1645
1646 l = strlen(contents);
1647
1648 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1649 !startswith(c->signature + c->index + 1, contents) ||
1650 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1651 return -ENXIO;
de1c301e
LP
1652
1653 nindex = c->index + 1 + l + 1;
1654 } else {
5cbe7492
LP
1655 char *e;
1656
de1c301e 1657 if (c->enclosing != 0)
9a17484d 1658 return -ENXIO;
de1c301e 1659
c2bc710b 1660 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END));
bc7fd8cd
LP
1661 if (!e) {
1662 m->poisoned = true;
de1c301e 1663 return -ENOMEM;
bc7fd8cd 1664 }
de1c301e
LP
1665
1666 nindex = e - c->signature;
1667 }
1668
0dd48768
YW
1669 /* Align contents to 8 byte boundary */
1670 if (!message_extend_body(m, 8, 0))
1671 return -ENOMEM;
de1c301e
LP
1672
1673 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1674 c->index = nindex;
1675
1676 return 0;
1677}
1678
1679static int bus_message_open_dict_entry(
1680 sd_bus_message *m,
1681 struct bus_container *c,
c1b9d935 1682 const char *contents,
0dd48768 1683 size_t *begin) {
de1c301e
LP
1684
1685 assert(m);
1686 assert(c);
1687 assert(contents);
c1b9d935 1688 assert(begin);
de1c301e
LP
1689
1690 if (!signature_is_pair(contents))
1691 return -EINVAL;
1692
1693 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1694 return -ENXIO;
de1c301e
LP
1695
1696 if (c->signature && c->signature[c->index]) {
1697 size_t l;
1698
1699 l = strlen(contents);
1700
1701 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1702 !startswith(c->signature + c->index + 1, contents) ||
1703 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1704 return -ENXIO;
de1c301e 1705 } else
9a17484d 1706 return -ENXIO;
de1c301e 1707
0dd48768
YW
1708 /* Align contents to 8 byte boundary */
1709 if (!message_extend_body(m, 8, 0))
1710 return -ENOMEM;
de1c301e
LP
1711
1712 return 0;
1713}
1714
d9f644e2 1715_public_ int sd_bus_message_open_container(
de1c301e
LP
1716 sd_bus_message *m,
1717 char type,
1718 const char *contents) {
1719
cf81c68e 1720 struct bus_container *c;
de1c301e 1721 uint32_t *array_size = NULL;
7a4b8512 1722 _cleanup_free_ char *signature = NULL;
39883f62 1723 size_t before, begin = 0;
de1c301e
LP
1724 int r;
1725
9d6c7c82
LP
1726 assert_return(m, -EINVAL);
1727 assert_return(!m->sealed, -EPERM);
1728 assert_return(contents, -EINVAL);
1729 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1730
1731 /* Make sure we have space for one more container */
319a4f4b 1732 if (!GREEDY_REALLOC(m->containers, m->n_containers + 1)) {
bc7fd8cd 1733 m->poisoned = true;
de1c301e 1734 return -ENOMEM;
bc7fd8cd
LP
1735 }
1736
9c65778d 1737 c = message_get_last_container(m);
de1c301e
LP
1738
1739 signature = strdup(contents);
bc7fd8cd
LP
1740 if (!signature) {
1741 m->poisoned = true;
de1c301e 1742 return -ENOMEM;
bc7fd8cd 1743 }
de1c301e 1744
b3af9646
LP
1745 /* Save old index in the parent container, in case we have to
1746 * abort this container */
1747 c->saved_index = c->index;
2ac7c17f 1748 before = m->body_size;
b3af9646 1749
de1c301e 1750 if (type == SD_BUS_TYPE_ARRAY)
0dd48768 1751 r = bus_message_open_array(m, c, contents, &array_size, &begin);
de1c301e
LP
1752 else if (type == SD_BUS_TYPE_VARIANT)
1753 r = bus_message_open_variant(m, c, contents);
1754 else if (type == SD_BUS_TYPE_STRUCT)
0dd48768 1755 r = bus_message_open_struct(m, c, contents, &begin);
de1c301e 1756 else if (type == SD_BUS_TYPE_DICT_ENTRY)
0dd48768 1757 r = bus_message_open_dict_entry(m, c, contents, &begin);
de1c301e
LP
1758 else
1759 r = -EINVAL;
7a4b8512 1760 if (r < 0)
de1c301e 1761 return r;
de1c301e
LP
1762
1763 /* OK, let's fill it in */
cf81c68e
ZJS
1764 m->containers[m->n_containers++] = (struct bus_container) {
1765 .enclosing = type,
1766 .signature = TAKE_PTR(signature),
1767 .array_size = array_size,
1768 .before = before,
1769 .begin = begin,
cf81c68e 1770 };
c1b9d935
LP
1771
1772 return 0;
1773}
1774
0dd48768
YW
1775_public_ int sd_bus_message_close_container(sd_bus_message *m) {
1776 struct bus_container *c;
c1b9d935 1777
0dd48768
YW
1778 assert_return(m, -EINVAL);
1779 assert_return(!m->sealed, -EPERM);
1780 assert_return(m->n_containers > 0, -EINVAL);
1781 assert_return(!m->poisoned, -ESTALE);
c1b9d935 1782
0dd48768 1783 c = message_get_last_container(m);
c1b9d935 1784
0dd48768
YW
1785 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1786 if (c->signature && c->signature[c->index] != 0)
1787 return -EINVAL;
c1b9d935 1788
0dd48768 1789 m->n_containers--;
c1b9d935 1790
0dd48768 1791 free(c->signature);
c1b9d935 1792
0dd48768
YW
1793 return 0;
1794}
de1c301e 1795
1b492614
LP
1796typedef struct {
1797 const char *types;
1798 unsigned n_struct;
1799 unsigned n_array;
1800} TypeStack;
1801
1802static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1803 assert(stack);
1804 assert(max > 0);
1805
1806 if (*i >= max)
1807 return -EINVAL;
1808
1809 stack[*i].types = types;
1810 stack[*i].n_struct = n_struct;
1811 stack[*i].n_array = n_array;
1812 (*i)++;
1813
1814 return 0;
1815}
1816
1817static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1818 assert(stack);
1819 assert(max > 0);
1820 assert(types);
1821 assert(n_struct);
1822 assert(n_array);
1823
1824 if (*i <= 0)
1825 return 0;
1826
1827 (*i)--;
1828 *types = stack[*i].types;
1829 *n_struct = stack[*i].n_struct;
1830 *n_array = stack[*i].n_array;
1831
1832 return 1;
1833}
1834
19fe49f6 1835_public_ int sd_bus_message_appendv(
de1c301e
LP
1836 sd_bus_message *m,
1837 const char *types,
1838 va_list ap) {
1839
1b492614
LP
1840 unsigned n_array, n_struct;
1841 TypeStack stack[BUS_CONTAINER_DEPTH];
1842 unsigned stack_ptr = 0;
de1c301e
LP
1843 int r;
1844
19fe49f6
FDP
1845 assert_return(m, -EINVAL);
1846 assert_return(types, -EINVAL);
1847 assert_return(!m->sealed, -EPERM);
1848 assert_return(!m->poisoned, -ESTALE);
de1c301e 1849
f5fbe71d 1850 n_array = UINT_MAX;
1b492614
LP
1851 n_struct = strlen(types);
1852
1853 for (;;) {
1854 const char *t;
1855
f5fbe71d 1856 if (n_array == 0 || (n_array == UINT_MAX && n_struct == 0)) {
1b492614
LP
1857 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1858 if (r < 0)
1859 return r;
1860 if (r == 0)
1861 break;
1862
1863 r = sd_bus_message_close_container(m);
1864 if (r < 0)
1865 return r;
1866
1867 continue;
1868 }
1869
1870 t = types;
f5fbe71d 1871 if (n_array != UINT_MAX)
313cefa1 1872 n_array--;
1b492614 1873 else {
313cefa1 1874 types++;
1b492614
LP
1875 n_struct--;
1876 }
1877
de1c301e
LP
1878 switch (*t) {
1879
1880 case SD_BUS_TYPE_BYTE: {
1881 uint8_t x;
1882
1883 x = (uint8_t) va_arg(ap, int);
1884 r = sd_bus_message_append_basic(m, *t, &x);
1885 break;
1886 }
1887
1888 case SD_BUS_TYPE_BOOLEAN:
1889 case SD_BUS_TYPE_INT32:
9a17484d
LP
1890 case SD_BUS_TYPE_UINT32:
1891 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1892 uint32_t x;
1893
9a17484d
LP
1894 /* We assume a boolean is the same as int32_t */
1895 assert_cc(sizeof(int32_t) == sizeof(int));
1896
de1c301e
LP
1897 x = va_arg(ap, uint32_t);
1898 r = sd_bus_message_append_basic(m, *t, &x);
1899 break;
1900 }
1901
1902 case SD_BUS_TYPE_INT16:
1903 case SD_BUS_TYPE_UINT16: {
1904 uint16_t x;
1905
1906 x = (uint16_t) va_arg(ap, int);
1907 r = sd_bus_message_append_basic(m, *t, &x);
1908 break;
1909 }
1910
1911 case SD_BUS_TYPE_INT64:
6cd37a5e 1912 case SD_BUS_TYPE_UINT64: {
de1c301e
LP
1913 uint64_t x;
1914
1915 x = va_arg(ap, uint64_t);
1916 r = sd_bus_message_append_basic(m, *t, &x);
1917 break;
1918 }
1919
6cd37a5e
LP
1920 case SD_BUS_TYPE_DOUBLE: {
1921 double x;
1922
1923 x = va_arg(ap, double);
1924 r = sd_bus_message_append_basic(m, *t, &x);
1925 break;
1926 }
1927
de1c301e
LP
1928 case SD_BUS_TYPE_STRING:
1929 case SD_BUS_TYPE_OBJECT_PATH:
1930 case SD_BUS_TYPE_SIGNATURE: {
1931 const char *x;
1932
1933 x = va_arg(ap, const char*);
1934 r = sd_bus_message_append_basic(m, *t, x);
1935 break;
1936 }
1937
de1c301e 1938 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1939 size_t k;
1940
1941 r = signature_element_length(t + 1, &k);
1942 if (r < 0)
1943 return r;
1944
1945 {
1946 char s[k + 1];
de1c301e
LP
1947 memcpy(s, t + 1, k);
1948 s[k] = 0;
de1c301e
LP
1949
1950 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1951 if (r < 0)
1952 return r;
1b492614 1953 }
de1c301e 1954
f5fbe71d 1955 if (n_array == UINT_MAX) {
1b492614
LP
1956 types += k;
1957 n_struct -= k;
de1c301e
LP
1958 }
1959
1b492614
LP
1960 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1961 if (r < 0)
1962 return r;
1963
1964 types = t + 1;
1965 n_struct = k;
1966 n_array = va_arg(ap, unsigned);
1967
de1c301e
LP
1968 break;
1969 }
1970
1971 case SD_BUS_TYPE_VARIANT: {
1972 const char *s;
1973
1974 s = va_arg(ap, const char*);
1975 if (!s)
1976 return -EINVAL;
1977
1978 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1979 if (r < 0)
1980 return r;
1981
1b492614 1982 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
1983 if (r < 0)
1984 return r;
1985
1b492614
LP
1986 types = s;
1987 n_struct = strlen(s);
f5fbe71d 1988 n_array = UINT_MAX;
1b492614 1989
de1c301e
LP
1990 break;
1991 }
1992
1993 case SD_BUS_TYPE_STRUCT_BEGIN:
1994 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1995 size_t k;
1996
1997 r = signature_element_length(t, &k);
1998 if (r < 0)
1999 return r;
2000
2001 {
2002 char s[k - 1];
2003
2004 memcpy(s, t + 1, k - 2);
2005 s[k - 2] = 0;
2006
2007 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2008 if (r < 0)
2009 return r;
1b492614 2010 }
de1c301e 2011
f5fbe71d 2012 if (n_array == UINT_MAX) {
1b492614
LP
2013 types += k - 1;
2014 n_struct -= k - 1;
2015 }
de1c301e 2016
1b492614
LP
2017 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2018 if (r < 0)
2019 return r;
de1c301e 2020
1b492614
LP
2021 types = t + 1;
2022 n_struct = k - 2;
f5fbe71d 2023 n_array = UINT_MAX;
de1c301e
LP
2024
2025 break;
2026 }
2027
2028 default:
2029 r = -EINVAL;
2030 }
2031
2032 if (r < 0)
2033 return r;
2034 }
2035
ebcf1f97 2036 return 1;
de1c301e
LP
2037}
2038
d9f644e2 2039_public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
de1c301e
LP
2040 va_list ap;
2041 int r;
2042
de1c301e 2043 va_start(ap, types);
19fe49f6 2044 r = sd_bus_message_appendv(m, types, ap);
de1c301e
LP
2045 va_end(ap);
2046
2047 return r;
2048}
2049
c1b9d935
LP
2050_public_ int sd_bus_message_append_array_space(
2051 sd_bus_message *m,
2052 char type,
2053 size_t size,
2054 void **ptr) {
2055
b3af9646
LP
2056 ssize_t align, sz;
2057 void *a;
2058 int r;
2059
9d6c7c82
LP
2060 assert_return(m, -EINVAL);
2061 assert_return(!m->sealed, -EPERM);
0039a203 2062 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
9d6c7c82
LP
2063 assert_return(ptr || size == 0, -EINVAL);
2064 assert_return(!m->poisoned, -ESTALE);
b3af9646
LP
2065
2066 align = bus_type_get_alignment(type);
2067 sz = bus_type_get_size(type);
2068
2069 assert_se(align > 0);
2070 assert_se(sz > 0);
2071
2072 if (size % sz != 0)
2073 return -EINVAL;
2074
2075 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2076 if (r < 0)
2077 return r;
2078
0dd48768 2079 a = message_extend_body(m, align, size);
bc7fd8cd
LP
2080 if (!a)
2081 return -ENOMEM;
b3af9646
LP
2082
2083 r = sd_bus_message_close_container(m);
2084 if (r < 0)
bc7fd8cd 2085 return r;
b3af9646
LP
2086
2087 *ptr = a;
2088 return 0;
b3af9646
LP
2089}
2090
7dcd79c2
LP
2091_public_ int sd_bus_message_append_array(
2092 sd_bus_message *m,
2093 char type,
2094 const void *ptr,
2095 size_t size) {
b3af9646
LP
2096 int r;
2097 void *p;
2098
9d6c7c82
LP
2099 assert_return(m, -EINVAL);
2100 assert_return(!m->sealed, -EPERM);
2101 assert_return(bus_type_is_trivial(type), -EINVAL);
2102 assert_return(ptr || size == 0, -EINVAL);
2103 assert_return(!m->poisoned, -ESTALE);
b3af9646 2104
f8e013f8 2105 r = sd_bus_message_append_array_space(m, type, size, &p);
b3af9646
LP
2106 if (r < 0)
2107 return r;
2108
75f32f04 2109 memcpy_safe(p, ptr, size);
b3af9646
LP
2110
2111 return 0;
2112}
2113
938bcbab
LP
2114_public_ int sd_bus_message_append_array_iovec(
2115 sd_bus_message *m,
2116 char type,
2117 const struct iovec *iov,
da6053d0 2118 unsigned n /* should be size_t, but is API now… 😞 */) {
938bcbab
LP
2119
2120 size_t size;
2121 unsigned i;
2122 void *p;
2123 int r;
2124
2125 assert_return(m, -EINVAL);
2126 assert_return(!m->sealed, -EPERM);
2127 assert_return(bus_type_is_trivial(type), -EINVAL);
2128 assert_return(iov || n == 0, -EINVAL);
2129 assert_return(!m->poisoned, -ESTALE);
2130
2131 size = IOVEC_TOTAL_SIZE(iov, n);
2132
2133 r = sd_bus_message_append_array_space(m, type, size, &p);
2134 if (r < 0)
2135 return r;
2136
2137 for (i = 0; i < n; i++) {
2138
2139 if (iov[i].iov_base)
2140 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2141 else
29804cc1 2142 memzero(p, iov[i].iov_len);
938bcbab
LP
2143
2144 p = (uint8_t*) p + iov[i].iov_len;
2145 }
2146
2147 return 0;
2148}
2149
7dcd79c2
LP
2150_public_ int sd_bus_message_append_array_memfd(
2151 sd_bus_message *m,
2152 char type,
2153 int memfd,
2154 uint64_t offset,
2155 uint64_t size) {
2156
453a0c29
LP
2157 _cleanup_close_ int copy_fd = -1;
2158 struct bus_body_part *part;
2159 ssize_t align, sz;
7dcd79c2 2160 uint64_t real_size;
453a0c29
LP
2161 void *a;
2162 int r;
2163
7dcd79c2 2164 assert_return(m, -EINVAL);
8ac43fee 2165 assert_return(memfd >= 0, -EBADF);
7dcd79c2
LP
2166 assert_return(bus_type_is_trivial(type), -EINVAL);
2167 assert_return(size > 0, -EINVAL);
2168 assert_return(!m->sealed, -EPERM);
2169 assert_return(!m->poisoned, -ESTALE);
453a0c29 2170
fac9c0d5 2171 r = memfd_set_sealed(memfd);
453a0c29
LP
2172 if (r < 0)
2173 return r;
2174
40164c2c 2175 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
453a0c29
LP
2176 if (copy_fd < 0)
2177 return copy_fd;
2178
7dcd79c2 2179 r = memfd_get_size(memfd, &real_size);
453a0c29
LP
2180 if (r < 0)
2181 return r;
2182
f5fbe71d 2183 if (offset == 0 && size == UINT64_MAX)
7dcd79c2
LP
2184 size = real_size;
2185 else if (offset + size > real_size)
2186 return -EMSGSIZE;
2187
453a0c29
LP
2188 align = bus_type_get_alignment(type);
2189 sz = bus_type_get_size(type);
2190
2191 assert_se(align > 0);
2192 assert_se(sz > 0);
2193
7dcd79c2
LP
2194 if (offset % align != 0)
2195 return -EINVAL;
2196
453a0c29
LP
2197 if (size % sz != 0)
2198 return -EINVAL;
2199
f5fbe71d 2200 if (size > (uint64_t) UINT32_MAX)
453a0c29
LP
2201 return -EINVAL;
2202
2203 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2204 if (r < 0)
2205 return r;
2206
0dd48768 2207 a = message_extend_body(m, align, 0);
453a0c29
LP
2208 if (!a)
2209 return -ENOMEM;
2210
2211 part = message_append_part(m);
2212 if (!part)
2213 return -ENOMEM;
2214
2215 part->memfd = copy_fd;
7dcd79c2 2216 part->memfd_offset = offset;
453a0c29
LP
2217 part->sealed = true;
2218 part->size = size;
2219 copy_fd = -1;
2220
2ac7c17f 2221 m->body_size += size;
0039a203 2222 message_extend_containers(m, size);
453a0c29
LP
2223
2224 return sd_bus_message_close_container(m);
2225}
2226
7dcd79c2
LP
2227_public_ int sd_bus_message_append_string_memfd(
2228 sd_bus_message *m,
2229 int memfd,
2230 uint64_t offset,
2231 uint64_t size) {
2232
5cbe7492
LP
2233 _cleanup_close_ int copy_fd = -1;
2234 struct bus_body_part *part;
2235 struct bus_container *c;
7dcd79c2 2236 uint64_t real_size;
5cbe7492
LP
2237 void *a;
2238 int r;
2239
55736ed0 2240 assert_return(m, -EINVAL);
8ac43fee 2241 assert_return(memfd >= 0, -EBADF);
7dcd79c2 2242 assert_return(size > 0, -EINVAL);
55736ed0
LP
2243 assert_return(!m->sealed, -EPERM);
2244 assert_return(!m->poisoned, -ESTALE);
5cbe7492 2245
fac9c0d5 2246 r = memfd_set_sealed(memfd);
5cbe7492
LP
2247 if (r < 0)
2248 return r;
2249
40164c2c 2250 copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
5cbe7492
LP
2251 if (copy_fd < 0)
2252 return copy_fd;
2253
7dcd79c2 2254 r = memfd_get_size(memfd, &real_size);
5cbe7492
LP
2255 if (r < 0)
2256 return r;
2257
f5fbe71d 2258 if (offset == 0 && size == UINT64_MAX)
7dcd79c2
LP
2259 size = real_size;
2260 else if (offset + size > real_size)
2261 return -EMSGSIZE;
2262
5cbe7492
LP
2263 /* We require this to be NUL terminated */
2264 if (size == 0)
2265 return -EINVAL;
2266
f5fbe71d 2267 if (size > (uint64_t) UINT32_MAX)
5cbe7492
LP
2268 return -EINVAL;
2269
9c65778d 2270 c = message_get_last_container(m);
5cbe7492
LP
2271 if (c->signature && c->signature[c->index]) {
2272 /* Container signature is already set */
2273
2274 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2275 return -ENXIO;
2276 } else {
2277 char *e;
2278
ad67ef27 2279 /* Maybe we can append to the signature? But only if this is the top-level container */
5cbe7492
LP
2280 if (c->enclosing != 0)
2281 return -ENXIO;
2282
c2bc710b 2283 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING));
5cbe7492
LP
2284 if (!e) {
2285 m->poisoned = true;
2286 return -ENOMEM;
2287 }
2288 }
2289
0dd48768
YW
2290 a = message_extend_body(m, 4, 4);
2291 if (!a)
2292 return -ENOMEM;
5cbe7492 2293
0dd48768 2294 *(uint32_t*) a = size - 1;
5cbe7492
LP
2295
2296 part = message_append_part(m);
2297 if (!part)
2298 return -ENOMEM;
2299
2300 part->memfd = copy_fd;
7dcd79c2 2301 part->memfd_offset = offset;
5cbe7492
LP
2302 part->sealed = true;
2303 part->size = size;
2304 copy_fd = -1;
2305
2ac7c17f 2306 m->body_size += size;
c1b9d935
LP
2307 message_extend_containers(m, size);
2308
5cbe7492
LP
2309 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2310 c->index++;
2311
2312 return 0;
2313}
2314
d9f644e2 2315_public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
55736ed0
LP
2316 int r;
2317
2318 assert_return(m, -EINVAL);
2319 assert_return(!m->sealed, -EPERM);
2320 assert_return(!m->poisoned, -ESTALE);
2321
2322 r = sd_bus_message_open_container(m, 'a', "s");
2323 if (r < 0)
2324 return r;
2325
2326 STRV_FOREACH(i, l) {
2327 r = sd_bus_message_append_basic(m, 's', *i);
2328 if (r < 0)
2329 return r;
2330 }
2331
2332 return sd_bus_message_close_container(m);
2333}
2334
81389225 2335static int bus_message_close_header(sd_bus_message *m) {
81389225
LP
2336 assert(m);
2337
0dd48768
YW
2338 /* The actual user data is finished now, we just complete the variant and struct now. Remember
2339 * this position, so that during parsing we know where to put the outer container end. */
2ac7c17f 2340 m->user_body_size = m->body_size;
81389225 2341
0dd48768
YW
2342 m->header->fields_size = m->fields_size;
2343 m->header->body_size = m->body_size;
81389225
LP
2344
2345 return 0;
2346}
2347
75bcbcf2 2348_public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
81389225 2349 struct bus_body_part *part;
2ac7c17f 2350 size_t a;
81389225
LP
2351 unsigned i;
2352 int r;
2353
75bcbcf2 2354 assert_return(m, -EINVAL);
81389225
LP
2355
2356 if (m->sealed)
2357 return -EPERM;
2358
2359 if (m->n_containers > 0)
2360 return -EBADMSG;
2361
2362 if (m->poisoned)
2363 return -ESTALE;
2364
0dd48768 2365 if (cookie > UINT32_MAX)
15411c0c 2366 return -EOPNOTSUPP;
2ac7c17f 2367
81389225
LP
2368 /* In vtables the return signature of method calls is listed,
2369 * let's check if they match if this is a response */
2370 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2371 m->enforced_reply_signature &&
2372 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2373 return -ENOMSG;
2374
0dd48768
YW
2375 /* If there's a non-trivial signature set, then add it in here */
2376 if (!isempty(m->root_container.signature)) {
81389225
LP
2377 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2378 if (r < 0)
2379 return r;
2380 }
2381
2382 if (m->n_fds > 0) {
2383 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2384 if (r < 0)
2385 return r;
2386 }
2387
2388 r = bus_message_close_header(m);
2389 if (r < 0)
2390 return r;
2391
0dd48768 2392 m->header->serial = (uint32_t) cookie;
2ac7c17f 2393
75bcbcf2 2394 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
81389225
LP
2395
2396 /* Add padding at the end of the fields part, since we know
2397 * the body needs to start at an 8 byte alignment. We made
2398 * sure we allocated enough space for this, so all we need to
2399 * do here is to zero it out. */
2ac7c17f 2400 a = ALIGN8(m->fields_size) - m->fields_size;
81389225 2401 if (a > 0)
2ac7c17f 2402 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
81389225
LP
2403
2404 /* If this is something we can send as memfd, then let's seal
2405 the memfd now. Note that we can send memfds as payload only
2406 for directed messages, and not for broadcasts. */
2a0958d2 2407 if (m->destination && m->bus->use_memfd) {
81389225 2408 MESSAGE_FOREACH_PART(part, i, m)
2ac7c17f
LP
2409 if (part->memfd >= 0 &&
2410 !part->sealed &&
2411 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2412 part != m->body_end) { /* The last part may never be sent as memfd */
8e959fbf
LP
2413 uint64_t sz;
2414
2415 /* Try to seal it if that makes
2416 * sense. First, unmap our own map to
2417 * make sure we don't keep it busy. */
81389225
LP
2418 bus_body_part_unmap(part);
2419
8e959fbf
LP
2420 /* Then, sync up real memfd size */
2421 sz = part->size;
73843b52
LP
2422 r = memfd_set_size(part->memfd, sz);
2423 if (r < 0)
2424 return r;
8e959fbf
LP
2425
2426 /* Finally, try to seal */
73843b52 2427 if (memfd_set_sealed(part->memfd) >= 0)
81389225
LP
2428 part->sealed = true;
2429 }
2430 }
2431
2ac7c17f 2432 m->root_container.end = m->user_body_size;
81389225 2433 m->root_container.index = 0;
81389225
LP
2434
2435 m->sealed = true;
2436
2437 return 0;
2438}
2439
a392d361 2440int bus_body_part_map(struct bus_body_part *part) {
453a0c29 2441 void *p;
7dcd79c2 2442 size_t psz, shift;
453a0c29
LP
2443
2444 assert_se(part);
2445
2446 if (part->data)
2447 return 0;
2448
2449 if (part->size <= 0)
2450 return 0;
2451
1307c3ff
LP
2452 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2453 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2454 static const uint8_t zeroes[7] = { };
2455 part->data = (void*) zeroes;
2456 return 0;
2457 }
2458
b98f393d 2459 shift = PAGE_OFFSET(part->memfd_offset);
7dcd79c2 2460 psz = PAGE_ALIGN(part->size + shift);
453a0c29
LP
2461
2462 if (part->memfd >= 0)
7dcd79c2 2463 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
453a0c29
LP
2464 else if (part->is_zero)
2465 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2466 else
2467 return -EINVAL;
2468
2469 if (p == MAP_FAILED)
2470 return -errno;
2471
2472 part->mapped = psz;
7dcd79c2
LP
2473 part->mmap_begin = p;
2474 part->data = (uint8_t*) p + shift;
a392d361
LP
2475 part->munmap_this = true;
2476
453a0c29
LP
2477 return 0;
2478}
2479
a392d361
LP
2480void bus_body_part_unmap(struct bus_body_part *part) {
2481
2482 assert_se(part);
2483
2484 if (part->memfd < 0)
2485 return;
2486
7dcd79c2 2487 if (!part->mmap_begin)
a392d361
LP
2488 return;
2489
bf30e48f
KS
2490 if (!part->munmap_this)
2491 return;
a392d361 2492
7dcd79c2 2493 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
a392d361 2494
7dcd79c2 2495 part->mmap_begin = NULL;
a392d361
LP
2496 part->data = NULL;
2497 part->mapped = 0;
2498 part->munmap_this = false;
2499
2500 return;
2501}
2502
7b058942
LP
2503static bool message_end_of_signature(sd_bus_message *m) {
2504 struct bus_container *c;
2505
2506 assert(m);
2507
9c65778d 2508 c = message_get_last_container(m);
7b058942
LP
2509 return !c->signature || c->signature[c->index] == 0;
2510}
2511
9a17484d
LP
2512static bool message_end_of_array(sd_bus_message *m, size_t index) {
2513 struct bus_container *c;
de1c301e 2514
9a17484d 2515 assert(m);
de1c301e 2516
9c65778d 2517 c = message_get_last_container(m);
6647dc66 2518 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 2519 return false;
de1c301e 2520
0dd48768
YW
2521 assert(c->array_size);
2522 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
2523}
2524
1405bef3 2525_public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
7b058942
LP
2526 assert_return(m, -EINVAL);
2527 assert_return(m->sealed, -EPERM);
2528
2529 if (complete && m->n_containers > 0)
2530 return false;
2531
2532 if (message_end_of_signature(m))
2533 return true;
2534
2535 if (message_end_of_array(m, m->rindex))
2536 return true;
2537
2538 return false;
2539}
2540
bc7fd8cd
LP
2541static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2542 struct bus_body_part *part;
2543 size_t begin;
453a0c29
LP
2544 int r;
2545
bc7fd8cd
LP
2546 assert(m);
2547
2548 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2549 part = m->cached_rindex_part;
2550 begin = m->cached_rindex_part_begin;
2551 } else {
2552 part = &m->body;
2553 begin = 0;
2554 }
2555
2556 while (part) {
2557 if (index < begin)
2558 return NULL;
2559
2560 if (index + sz <= begin + part->size) {
453a0c29 2561
a392d361 2562 r = bus_body_part_map(part);
453a0c29
LP
2563 if (r < 0)
2564 return NULL;
2565
bc7fd8cd 2566 if (p)
b17af3e5
ZJS
2567 *p = part->data ? (uint8_t*) part->data + index - begin
2568 : NULL; /* Avoid dereferencing a NULL pointer. */
bc7fd8cd
LP
2569
2570 m->cached_rindex_part = part;
2571 m->cached_rindex_part_begin = begin;
2572
2573 return part;
2574 }
2575
453a0c29 2576 begin += part->size;
bc7fd8cd
LP
2577 part = part->next;
2578 }
2579
2580 return NULL;
2581}
2582
2583static int message_peek_body(
2584 sd_bus_message *m,
2585 size_t *rindex,
2586 size_t align,
2587 size_t nbytes,
2588 void **ret) {
2589
2590 size_t k, start, end, padding;
2591 struct bus_body_part *part;
2592 uint8_t *q;
2593
de1c301e 2594 assert(m);
9a17484d
LP
2595 assert(rindex);
2596 assert(align > 0);
de1c301e 2597
89b6a3f1
YW
2598 start = ALIGN_TO(*rindex, align);
2599 if (start > m->user_body_size)
2600 return -EBADMSG;
2601
bc7fd8cd 2602 padding = start - *rindex;
bc7fd8cd 2603
89b6a3f1
YW
2604 /* Avoid overflow below */
2605 if (nbytes > SIZE_MAX - start)
2606 return -EBADMSG;
2607
2608 end = start + nbytes;
2ac7c17f 2609 if (end > m->user_body_size)
bc7fd8cd
LP
2610 return -EBADMSG;
2611
2612 part = find_part(m, *rindex, padding, (void**) &q);
2613 if (!part)
2614 return -EBADMSG;
2615
2616 if (q) {
2617 /* Verify padding */
2618 for (k = 0; k < padding; k++)
2619 if (q[k] != 0)
2620 return -EBADMSG;
2621 }
2622
2623 part = find_part(m, start, nbytes, (void**) &q);
5f7e8903 2624 if (!part || (nbytes > 0 && !q))
bc7fd8cd
LP
2625 return -EBADMSG;
2626
2627 *rindex = end;
2628
2629 if (ret)
2630 *ret = q;
2631
18f5b48f 2632 return 0;
9a17484d 2633}
de1c301e 2634
ac89bf1d 2635static bool validate_nul(const char *s, size_t l) {
de1c301e 2636
9a17484d
LP
2637 /* Check for NUL chars in the string */
2638 if (memchr(s, 0, l))
2639 return false;
de1c301e 2640
9a17484d
LP
2641 /* Check for NUL termination */
2642 if (s[l] != 0)
2643 return false;
de1c301e 2644
ac89bf1d
LP
2645 return true;
2646}
2647
2648static bool validate_string(const char *s, size_t l) {
2649
2650 if (!validate_nul(s, l))
2651 return false;
2652
9a17484d
LP
2653 /* Check if valid UTF8 */
2654 if (!utf8_is_valid(s))
2655 return false;
2656
2657 return true;
de1c301e
LP
2658}
2659
9a17484d 2660static bool validate_signature(const char *s, size_t l) {
de1c301e 2661
ac89bf1d 2662 if (!validate_nul(s, l))
9a17484d 2663 return false;
de1c301e 2664
9a17484d
LP
2665 /* Check if valid signature */
2666 if (!signature_is_valid(s, true))
2667 return false;
2668
2669 return true;
2670}
2671
ac89bf1d
LP
2672static bool validate_object_path(const char *s, size_t l) {
2673
2674 if (!validate_nul(s, l))
2675 return false;
2676
2677 if (!object_path_is_valid(s))
2678 return false;
2679
2680 return true;
2681}
2682
d9f644e2 2683_public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
9a17484d 2684 struct bus_container *c;
6647dc66 2685 size_t rindex;
9a17484d 2686 void *q;
0dcd14b9 2687 int r;
9a17484d 2688
9d6c7c82
LP
2689 assert_return(m, -EINVAL);
2690 assert_return(m->sealed, -EPERM);
2691 assert_return(bus_type_is_basic(type), -EINVAL);
de1c301e 2692
7b058942 2693 if (message_end_of_signature(m))
430fb8fa 2694 return -ENXIO;
9a17484d 2695
1daf8121
LP
2696 if (message_end_of_array(m, m->rindex))
2697 return 0;
2698
9c65778d 2699 c = message_get_last_container(m);
9a17484d
LP
2700 if (c->signature[c->index] != type)
2701 return -ENXIO;
2702
6647dc66 2703 rindex = m->rindex;
9a17484d 2704
0dd48768
YW
2705 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
2706 uint32_t l;
2707 bool ok;
6647dc66 2708
0dd48768
YW
2709 r = message_peek_body(m, &rindex, 4, 4, &q);
2710 if (r < 0)
2711 return r;
6647dc66 2712
0dd48768
YW
2713 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2714 if (l == UINT32_MAX)
2715 /* avoid overflow right below */
2716 return -EBADMSG;
9a17484d 2717
0dd48768
YW
2718 r = message_peek_body(m, &rindex, 1, l+1, &q);
2719 if (r < 0)
2720 return r;
0dcd14b9 2721
0dd48768
YW
2722 if (type == SD_BUS_TYPE_OBJECT_PATH)
2723 ok = validate_object_path(q, l);
2724 else
2725 ok = validate_string(q, l);
2726 if (!ok)
2727 return -EBADMSG;
de1c301e 2728
0dd48768
YW
2729 if (p)
2730 *(const char**) p = q;
9a17484d 2731
0dd48768
YW
2732 } else if (type == SD_BUS_TYPE_SIGNATURE) {
2733 uint8_t l;
9a17484d 2734
0dd48768
YW
2735 r = message_peek_body(m, &rindex, 1, 1, &q);
2736 if (r < 0)
2737 return r;
6647dc66 2738
0dd48768
YW
2739 l = *(uint8_t*) q;
2740 if (l == UINT8_MAX)
2741 /* avoid overflow right below */
2742 return -EBADMSG;
9a17484d 2743
0dd48768
YW
2744 r = message_peek_body(m, &rindex, 1, l+1, &q);
2745 if (r < 0)
2746 return r;
0dcd14b9 2747
0dd48768
YW
2748 if (!validate_signature(q, l))
2749 return -EBADMSG;
de1c301e 2750
0dd48768
YW
2751 if (p)
2752 *(const char**) p = q;
de1c301e 2753
0dd48768
YW
2754 } else {
2755 ssize_t sz, align;
de1c301e 2756
0dd48768
YW
2757 align = bus_type_get_alignment(type);
2758 assert(align > 0);
6647dc66 2759
0dd48768
YW
2760 sz = bus_type_get_size(type);
2761 assert(sz > 0);
6647dc66 2762
0dd48768 2763 r = message_peek_body(m, &rindex, align, sz, &q);
6647dc66 2764 if (r < 0)
9a17484d 2765 return r;
9a17484d 2766
0dd48768 2767 switch (type) {
9a17484d 2768
0dd48768
YW
2769 case SD_BUS_TYPE_BYTE:
2770 if (p)
2771 *(uint8_t*) p = *(uint8_t*) q;
2772 break;
9a17484d 2773
0dd48768 2774 case SD_BUS_TYPE_BOOLEAN:
0dcd14b9 2775 if (p)
0dd48768
YW
2776 *(int*) p = !!*(uint32_t*) q;
2777 break;
9a17484d 2778
0dd48768
YW
2779 case SD_BUS_TYPE_INT16:
2780 case SD_BUS_TYPE_UINT16:
2781 if (p)
2782 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
2783 break;
6647dc66 2784
0dd48768
YW
2785 case SD_BUS_TYPE_INT32:
2786 case SD_BUS_TYPE_UINT32:
2787 if (p)
2788 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2789 break;
6647dc66 2790
0dd48768
YW
2791 case SD_BUS_TYPE_INT64:
2792 case SD_BUS_TYPE_UINT64:
2793 case SD_BUS_TYPE_DOUBLE:
2794 if (p)
2795 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
2796 break;
902000c1 2797
0dd48768
YW
2798 case SD_BUS_TYPE_UNIX_FD: {
2799 uint32_t j;
2c93b4ef 2800
0dd48768
YW
2801 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2802 if (j >= m->n_fds)
2c93b4ef
LP
2803 return -EBADMSG;
2804
0dcd14b9 2805 if (p)
0dd48768
YW
2806 *(int*) p = m->fds[j];
2807 break;
2808 }
6647dc66 2809
0dd48768
YW
2810 default:
2811 assert_not_reached();
6647dc66 2812 }
9a17484d
LP
2813 }
2814
6647dc66
LP
2815 m->rindex = rindex;
2816
9a17484d
LP
2817 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2818 c->index++;
2819
2820 return 1;
de1c301e
LP
2821}
2822
9a17484d
LP
2823static int bus_message_enter_array(
2824 sd_bus_message *m,
2825 struct bus_container *c,
2826 const char *contents,
0dd48768 2827 uint32_t **array_size) {
9a17484d
LP
2828
2829 size_t rindex;
2830 void *q;
0dd48768 2831 int alignment, r;
9a17484d
LP
2832
2833 assert(m);
2834 assert(c);
2835 assert(contents);
2836 assert(array_size);
2837
29ddb38f 2838 if (!signature_is_single(contents, true))
de1c301e 2839 return -EINVAL;
9a17484d 2840
9a17484d 2841 if (!c->signature || c->signature[c->index] == 0)
6647dc66 2842 return -ENXIO;
9a17484d
LP
2843
2844 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2845 return -ENXIO;
2846
2847 if (!startswith(c->signature + c->index + 1, contents))
2848 return -ENXIO;
2849
2850 rindex = m->rindex;
9a17484d 2851
0dd48768
YW
2852 r = message_peek_body(m, &rindex, 4, 4, &q);
2853 if (r < 0)
2854 return r;
d6385068 2855
0dd48768 2856 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
d6385068 2857 return -EBADMSG;
6647dc66 2858
0dd48768
YW
2859 alignment = bus_type_get_alignment(contents[0]);
2860 if (alignment < 0)
2861 return alignment;
6647dc66 2862
0dd48768 2863 r = message_peek_body(m, &rindex, alignment, 0, NULL);
9a17484d
LP
2864 if (r < 0)
2865 return r;
9a17484d 2866
0dd48768 2867 *array_size = (uint32_t*) q;
9a17484d 2868
0dd48768 2869 m->rindex = rindex;
6647dc66 2870
0dd48768
YW
2871 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2872 c->index += 1 + strlen(contents);
6647dc66 2873
0dd48768 2874 return 1;
6647dc66
LP
2875}
2876
0dd48768 2877static int bus_message_enter_variant(
6647dc66
LP
2878 sd_bus_message *m,
2879 struct bus_container *c,
0dd48768 2880 const char *contents) {
6647dc66 2881
0dd48768
YW
2882 size_t rindex;
2883 uint8_t l;
2884 void *q;
6647dc66
LP
2885 int r;
2886
2887 assert(m);
2888 assert(c);
2889 assert(contents);
6647dc66 2890
0dd48768
YW
2891 if (!signature_is_single(contents, false))
2892 return -EINVAL;
6647dc66 2893
0dd48768
YW
2894 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2895 return -EINVAL;
6647dc66 2896
0dd48768
YW
2897 if (!c->signature || c->signature[c->index] == 0)
2898 return -ENXIO;
6647dc66 2899
0dd48768
YW
2900 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2901 return -ENXIO;
2902
2903 rindex = m->rindex;
2904
2905 r = message_peek_body(m, &rindex, 1, 1, &q);
2906 if (r < 0)
2907 return r;
2908
2909 l = *(uint8_t*) q;
2910 if (l == UINT8_MAX)
2911 /* avoid overflow right below */
2912 return -EBADMSG;
2913
2914 r = message_peek_body(m, &rindex, 1, l+1, &q);
2915 if (r < 0)
2916 return r;
2917
2918 if (!validate_signature(q, l))
2919 return -EBADMSG;
2920
2921 if (!streq(q, contents))
2922 return -ENXIO;
2923
2924 m->rindex = rindex;
2925
2926 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2927 c->index++;
2928
2929 return 1;
de1c301e
LP
2930}
2931
9a17484d
LP
2932static int bus_message_enter_struct(
2933 sd_bus_message *m,
2934 struct bus_container *c,
0dd48768 2935 const char *contents) {
9a17484d
LP
2936
2937 size_t l;
2938 int r;
2939
2940 assert(m);
2941 assert(c);
2942 assert(contents);
2943
2944 if (!signature_is_valid(contents, false))
2945 return -EINVAL;
2946
2947 if (!c->signature || c->signature[c->index] == 0)
6647dc66 2948 return -ENXIO;
9a17484d
LP
2949
2950 l = strlen(contents);
2951
2952 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2953 !startswith(c->signature + c->index + 1, contents) ||
2954 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2955 return -ENXIO;
2956
0dd48768 2957 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
6647dc66 2958 if (r < 0)
9a17484d
LP
2959 return r;
2960
2961 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2962 c->index += 1 + l + 1;
2963
2964 return 1;
2965}
2966
2967static int bus_message_enter_dict_entry(
2968 sd_bus_message *m,
2969 struct bus_container *c,
0dd48768 2970 const char *contents) {
9a17484d
LP
2971
2972 size_t l;
2973 int r;
2974
2975 assert(m);
2976 assert(c);
2977 assert(contents);
2978
2979 if (!signature_is_pair(contents))
2980 return -EINVAL;
2981
2982 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2983 return -ENXIO;
2984
2985 if (!c->signature || c->signature[c->index] == 0)
2986 return 0;
2987
2988 l = strlen(contents);
2989
2990 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2991 !startswith(c->signature + c->index + 1, contents) ||
2992 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2993 return -ENXIO;
2994
0dd48768 2995 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
6647dc66 2996 if (r < 0)
9a17484d
LP
2997 return r;
2998
2999 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3000 c->index += 1 + l + 1;
3001
3002 return 1;
3003}
3004
d9f644e2
ZJS
3005_public_ int sd_bus_message_enter_container(sd_bus_message *m,
3006 char type,
3007 const char *contents) {
cf81c68e 3008 struct bus_container *c;
9a17484d 3009 uint32_t *array_size = NULL;
7a4b8512 3010 _cleanup_free_ char *signature = NULL;
0dd48768 3011 size_t before;
9a17484d
LP
3012 int r;
3013
275b39fe
LP
3014 assert_return(m, -EINVAL);
3015 assert_return(m->sealed, -EPERM);
3016 assert_return(type != 0 || !contents, -EINVAL);
3017
3018 if (type == 0 || !contents) {
3019 const char *cc;
3020 char tt;
3021
3022 /* Allow entering into anonymous containers */
3023 r = sd_bus_message_peek_type(m, &tt, &cc);
18f5b48f 3024 if (r < 0)
275b39fe
LP
3025 return r;
3026
3027 if (type != 0 && type != tt)
3028 return -ENXIO;
3029
3030 if (contents && !streq(contents, cc))
3031 return -ENXIO;
3032
3033 type = tt;
3034 contents = cc;
3035 }
9a17484d 3036
ed205a6b
LP
3037 /*
3038 * We enforce a global limit on container depth, that is much
3039 * higher than the 32 structs and 32 arrays the specification
3040 * mandates. This is simpler to implement for us, and we need
3041 * this only to ensure our container array doesn't grow
3042 * without bounds. We are happy to return any data from a
3043 * message as long as the data itself is valid, even if the
3044 * overall message might be not.
3045 *
3046 * Note that the message signature is validated when
3047 * parsing the headers, and that validation does check the
3048 * 32/32 limit.
3049 *
3050 * Note that the specification defines no limits on the depth
3051 * of stacked variants, but we do.
3052 */
3053 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3054 return -EBADMSG;
3055
319a4f4b 3056 if (!GREEDY_REALLOC(m->containers, m->n_containers + 1))
9a17484d 3057 return -ENOMEM;
9a17484d 3058
7b058942 3059 if (message_end_of_signature(m))
430fb8fa 3060 return -ENXIO;
9a17484d 3061
1daf8121
LP
3062 if (message_end_of_array(m, m->rindex))
3063 return 0;
3064
9c65778d 3065 c = message_get_last_container(m);
7b058942 3066
9a17484d
LP
3067 signature = strdup(contents);
3068 if (!signature)
3069 return -ENOMEM;
3070
b3af9646
LP
3071 c->saved_index = c->index;
3072 before = m->rindex;
3073
9a17484d 3074 if (type == SD_BUS_TYPE_ARRAY)
0dd48768 3075 r = bus_message_enter_array(m, c, contents, &array_size);
9a17484d 3076 else if (type == SD_BUS_TYPE_VARIANT)
0dd48768 3077 r = bus_message_enter_variant(m, c, contents);
9a17484d 3078 else if (type == SD_BUS_TYPE_STRUCT)
0dd48768 3079 r = bus_message_enter_struct(m, c, contents);
9a17484d 3080 else if (type == SD_BUS_TYPE_DICT_ENTRY)
0dd48768 3081 r = bus_message_enter_dict_entry(m, c, contents);
9a17484d
LP
3082 else
3083 r = -EINVAL;
7a4b8512 3084 if (r <= 0)
9a17484d 3085 return r;
9a17484d
LP
3086
3087 /* OK, let's fill it in */
cf81c68e
ZJS
3088 m->containers[m->n_containers++] = (struct bus_container) {
3089 .enclosing = type,
3090 .signature = TAKE_PTR(signature),
3091
3092 .before = before,
3093 .begin = m->rindex,
3094 /* Unary type has fixed size of 1, but virtual size of 0 */
0dd48768 3095 .end = m->rindex,
cf81c68e 3096 .array_size = array_size,
cf81c68e 3097 };
9a17484d
LP
3098
3099 return 1;
3100}
3101
d9f644e2 3102_public_ int sd_bus_message_exit_container(sd_bus_message *m) {
9a17484d
LP
3103 struct bus_container *c;
3104
9d6c7c82
LP
3105 assert_return(m, -EINVAL);
3106 assert_return(m->sealed, -EPERM);
f959af20 3107 assert_return(m->n_containers > 0, -ENXIO);
9a17484d 3108
9c65778d 3109 c = message_get_last_container(m);
6647dc66
LP
3110
3111 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3112 if (c->signature && c->signature[c->index] != 0)
3113 return -EBUSY;
3114 }
3115
0dd48768 3116 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
9a17484d
LP
3117 uint32_t l;
3118
3119 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3120 if (c->begin + l != m->rindex)
3121 return -EBUSY;
9a17484d
LP
3122 }
3123
6d1e0f4f 3124 message_free_last_container(m);
9a17484d
LP
3125
3126 return 1;
3127}
3128
b3af9646
LP
3129static void message_quit_container(sd_bus_message *m) {
3130 struct bus_container *c;
3131
3132 assert(m);
3133 assert(m->sealed);
3134 assert(m->n_containers > 0);
3135
b3af9646 3136 /* Undo seeks */
9c65778d 3137 c = message_get_last_container(m);
b3af9646
LP
3138 assert(m->rindex >= c->before);
3139 m->rindex = c->before;
3140
3141 /* Free container */
6d1e0f4f 3142 message_free_last_container(m);
b3af9646
LP
3143
3144 /* Correct index of new top-level container */
9c65778d 3145 c = message_get_last_container(m);
b3af9646
LP
3146 c->index = c->saved_index;
3147}
3148
d9f644e2 3149_public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
9a17484d
LP
3150 struct bus_container *c;
3151 int r;
3152
c430fee6
LP
3153 assert_return(m, -EINVAL);
3154 assert_return(m->sealed, -EPERM);
9a17484d 3155
7b058942 3156 if (message_end_of_signature(m))
9a17484d
LP
3157 goto eof;
3158
3159 if (message_end_of_array(m, m->rindex))
3160 goto eof;
3161
9c65778d 3162 c = message_get_last_container(m);
7b058942 3163
9a17484d
LP
3164 if (bus_type_is_basic(c->signature[c->index])) {
3165 if (contents)
3166 *contents = NULL;
3167 if (type)
3168 *type = c->signature[c->index];
3169 return 1;
3170 }
3171
3172 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
3173
3174 if (contents) {
3175 size_t l;
9a17484d
LP
3176
3177 r = signature_element_length(c->signature+c->index+1, &l);
3178 if (r < 0)
3179 return r;
3180
7f546026 3181 /* signature_element_length does verification internally */
80a46c73 3182
ec6bda56 3183 /* The array element must not be empty */
7f546026
ZJS
3184 assert(l >= 1);
3185 if (free_and_strndup(&c->peeked_signature,
3186 c->signature + c->index + 1, l) < 0)
9a17484d
LP
3187 return -ENOMEM;
3188
7f546026 3189 *contents = c->peeked_signature;
9a17484d
LP
3190 }
3191
3192 if (type)
3193 *type = SD_BUS_TYPE_ARRAY;
3194
3195 return 1;
3196 }
3197
4c701096 3198 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
9a17484d
LP
3199
3200 if (contents) {
3201 size_t l;
9a17484d
LP
3202
3203 r = signature_element_length(c->signature+c->index, &l);
3204 if (r < 0)
3205 return r;
3206
ec6bda56 3207 assert(l >= 3);
7f546026
ZJS
3208 if (free_and_strndup(&c->peeked_signature,
3209 c->signature + c->index + 1, l - 2) < 0)
9a17484d
LP
3210 return -ENOMEM;
3211
7f546026 3212 *contents = c->peeked_signature;
9a17484d
LP
3213 }
3214
3215 if (type)
3216 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
3217
3218 return 1;
3219 }
3220
3221 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
3222 if (contents) {
0dd48768 3223 size_t rindex, l;
9a17484d
LP
3224 void *q;
3225
0dd48768
YW
3226 rindex = m->rindex;
3227 r = message_peek_body(m, &rindex, 1, 1, &q);
3228 if (r < 0)
3229 return r;
9a17484d 3230
0dd48768
YW
3231 l = *(uint8_t*) q;
3232 if (l == UINT8_MAX)
3233 /* avoid overflow right below */
3234 return -EBADMSG;
902000c1 3235
0dd48768
YW
3236 r = message_peek_body(m, &rindex, 1, l+1, &q);
3237 if (r < 0)
3238 return r;
6647dc66 3239
0dd48768
YW
3240 if (!validate_signature(q, l))
3241 return -EBADMSG;
6647dc66 3242
0dd48768 3243 *contents = q;
9a17484d
LP
3244 }
3245
3246 if (type)
3247 *type = SD_BUS_TYPE_VARIANT;
3248
3249 return 1;
3250 }
3251
3252 return -EINVAL;
3253
3254eof:
3255 if (type)
7b058942 3256 *type = 0;
9a17484d
LP
3257 if (contents)
3258 *contents = NULL;
3259 return 0;
3260}
3261
d9f644e2 3262_public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
3263 struct bus_container *c;
3264
9d6c7c82
LP
3265 assert_return(m, -EINVAL);
3266 assert_return(m->sealed, -EPERM);
9a17484d
LP
3267
3268 if (complete) {
bc7fd8cd 3269 message_reset_containers(m);
9a17484d 3270 m->rindex = 0;
9a17484d 3271
9c65778d 3272 c = message_get_last_container(m);
9a17484d 3273 } else {
9c65778d 3274 c = message_get_last_container(m);
9a17484d
LP
3275
3276 c->index = 0;
3277 m->rindex = c->begin;
3278 }
3279
3280 return !isempty(c->signature);
3281}
718db961 3282
11ce0db2 3283_public_ int sd_bus_message_readv(
1b492614
LP
3284 sd_bus_message *m,
3285 const char *types,
3286 va_list ap) {
9a17484d 3287
fe1d424d
LP
3288 unsigned n_array, n_struct;
3289 TypeStack stack[BUS_CONTAINER_DEPTH];
3290 unsigned stack_ptr = 0;
430fb8fa 3291 unsigned n_loop = 0;
9a17484d
LP
3292 int r;
3293
11ce0db2
VH
3294 assert_return(m, -EINVAL);
3295 assert_return(m->sealed, -EPERM);
3296 assert_return(types, -EINVAL);
1b492614 3297
430fb8fa 3298 if (isempty(types))
1b492614 3299 return 0;
9a17484d 3300
fe1d424d
LP
3301 /* Ideally, we'd just call ourselves recursively on every
3302 * complex type. However, the state of a va_list that is
3303 * passed to a function is undefined after that function
22509a8d 3304 * returns. This means we need to decode the va_list linearly
fe1d424d
LP
3305 * in a single stackframe. We hence implement our own
3306 * home-grown stack in an array. */
3307
f5fbe71d 3308 n_array = UINT_MAX; /* length of current array entries */
430fb8fa 3309 n_struct = strlen(types); /* length of current struct contents signature */
fe1d424d
LP
3310
3311 for (;;) {
3312 const char *t;
3313
430fb8fa
LP
3314 n_loop++;
3315
f5fbe71d 3316 if (n_array == 0 || (n_array == UINT_MAX && n_struct == 0)) {
fe1d424d
LP
3317 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
3318 if (r < 0)
3319 return r;
3320 if (r == 0)
3321 break;
3322
3323 r = sd_bus_message_exit_container(m);
3324 if (r < 0)
3325 return r;
3326
3327 continue;
3328 }
3329
3330 t = types;
f5fbe71d 3331 if (n_array != UINT_MAX)
313cefa1 3332 n_array--;
fe1d424d 3333 else {
313cefa1 3334 types++;
fe1d424d
LP
3335 n_struct--;
3336 }
3337
9a17484d
LP
3338 switch (*t) {
3339
3340 case SD_BUS_TYPE_BYTE:
3341 case SD_BUS_TYPE_BOOLEAN:
3342 case SD_BUS_TYPE_INT16:
3343 case SD_BUS_TYPE_UINT16:
3344 case SD_BUS_TYPE_INT32:
3345 case SD_BUS_TYPE_UINT32:
3346 case SD_BUS_TYPE_INT64:
3347 case SD_BUS_TYPE_UINT64:
3348 case SD_BUS_TYPE_DOUBLE:
3349 case SD_BUS_TYPE_STRING:
3350 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
3351 case SD_BUS_TYPE_SIGNATURE:
3352 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
3353 void *p;
3354
3355 p = va_arg(ap, void*);
3356 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
3357 if (r < 0)
3358 return r;
430fb8fa
LP
3359 if (r == 0) {
3360 if (n_loop <= 1)
3361 return 0;
3362
fe1d424d 3363 return -ENXIO;
430fb8fa 3364 }
fe1d424d 3365
9a17484d
LP
3366 break;
3367 }
3368
3369 case SD_BUS_TYPE_ARRAY: {
3370 size_t k;
3371
3372 r = signature_element_length(t + 1, &k);
3373 if (r < 0)
3374 return r;
3375
3376 {
9a17484d 3377 char s[k + 1];
9a17484d
LP
3378 memcpy(s, t + 1, k);
3379 s[k] = 0;
9a17484d
LP
3380
3381 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3382 if (r < 0)
3383 return r;
430fb8fa
LP
3384 if (r == 0) {
3385 if (n_loop <= 1)
3386 return 0;
3387
9a17484d 3388 return -ENXIO;
430fb8fa 3389 }
fe1d424d 3390 }
9a17484d 3391
f5fbe71d 3392 if (n_array == UINT_MAX) {
fe1d424d
LP
3393 types += k;
3394 n_struct -= k;
9a17484d
LP
3395 }
3396
fe1d424d
LP
3397 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3398 if (r < 0)
3399 return r;
3400
3401 types = t + 1;
3402 n_struct = k;
3403 n_array = va_arg(ap, unsigned);
3404
9a17484d
LP
3405 break;
3406 }
3407
3408 case SD_BUS_TYPE_VARIANT: {
3409 const char *s;
3410
3411 s = va_arg(ap, const char *);
3412 if (!s)
3413 return -EINVAL;
3414
3415 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
3416 if (r < 0)
3417 return r;
430fb8fa
LP
3418 if (r == 0) {
3419 if (n_loop <= 1)
3420 return 0;
3421
9a17484d 3422 return -ENXIO;
430fb8fa 3423 }
9a17484d 3424
fe1d424d 3425 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
3426 if (r < 0)
3427 return r;
9a17484d 3428
fe1d424d
LP
3429 types = s;
3430 n_struct = strlen(s);
f5fbe71d 3431 n_array = UINT_MAX;
fe1d424d 3432
9a17484d
LP
3433 break;
3434 }
3435
3436 case SD_BUS_TYPE_STRUCT_BEGIN:
3437 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3438 size_t k;
3439
3440 r = signature_element_length(t, &k);
3441 if (r < 0)
3442 return r;
3443
3444 {
3445 char s[k - 1];
3446 memcpy(s, t + 1, k - 2);
3447 s[k - 2] = 0;
3448
3449 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3450 if (r < 0)
3451 return r;
430fb8fa
LP
3452 if (r == 0) {
3453 if (n_loop <= 1)
3454 return 0;
9a17484d 3455 return -ENXIO;
430fb8fa 3456 }
fe1d424d 3457 }
9a17484d 3458
f5fbe71d 3459 if (n_array == UINT_MAX) {
fe1d424d
LP
3460 types += k - 1;
3461 n_struct -= k - 1;
3462 }
9a17484d 3463
fe1d424d
LP
3464 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3465 if (r < 0)
3466 return r;
9a17484d 3467
fe1d424d
LP
3468 types = t + 1;
3469 n_struct = k - 2;
f5fbe71d 3470 n_array = UINT_MAX;
9a17484d
LP
3471
3472 break;
3473 }
3474
3475 default:
fe1d424d 3476 return -EINVAL;
9a17484d 3477 }
9a17484d
LP
3478 }
3479
3480 return 1;
3481}
3482
d9f644e2 3483_public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
9a17484d
LP
3484 va_list ap;
3485 int r;
3486
9a17484d 3487 va_start(ap, types);
11ce0db2 3488 r = sd_bus_message_readv(m, types, ap);
9a17484d
LP
3489 va_end(ap);
3490
3491 return r;
3492}
3493
d9f644e2 3494_public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
9b07511d
LP
3495 int r;
3496
3497 assert_return(m, -EINVAL);
3498 assert_return(m->sealed, -EPERM);
9b07511d 3499
d9fba533
LP
3500 /* If types is NULL, read exactly one element */
3501 if (!types) {
3502 struct bus_container *c;
3503 size_t l;
3504
3505 if (message_end_of_signature(m))
3506 return -ENXIO;
3507
3508 if (message_end_of_array(m, m->rindex))
3509 return 0;
3510
9c65778d 3511 c = message_get_last_container(m);
d9fba533
LP
3512
3513 r = signature_element_length(c->signature + c->index, &l);
3514 if (r < 0)
3515 return r;
3516
2f82562b 3517 types = strndupa_safe(c->signature + c->index, l);
d9fba533 3518 }
9b07511d
LP
3519
3520 switch (*types) {
3521
d9fba533
LP
3522 case 0: /* Nothing to drop */
3523 return 0;
3524
9b07511d
LP
3525 case SD_BUS_TYPE_BYTE:
3526 case SD_BUS_TYPE_BOOLEAN:
3527 case SD_BUS_TYPE_INT16:
3528 case SD_BUS_TYPE_UINT16:
3529 case SD_BUS_TYPE_INT32:
3530 case SD_BUS_TYPE_UINT32:
3531 case SD_BUS_TYPE_INT64:
3532 case SD_BUS_TYPE_UINT64:
3533 case SD_BUS_TYPE_DOUBLE:
3534 case SD_BUS_TYPE_STRING:
3535 case SD_BUS_TYPE_OBJECT_PATH:
3536 case SD_BUS_TYPE_SIGNATURE:
3537 case SD_BUS_TYPE_UNIX_FD:
3538
3539 r = sd_bus_message_read_basic(m, *types, NULL);
3540 if (r <= 0)
3541 return r;
3542
3543 r = sd_bus_message_skip(m, types + 1);
3544 if (r < 0)
3545 return r;
3546
3547 return 1;
3548
3549 case SD_BUS_TYPE_ARRAY: {
3550 size_t k;
3551
3552 r = signature_element_length(types + 1, &k);
3553 if (r < 0)
3554 return r;
3555
3556 {
3557 char s[k+1];
3558 memcpy(s, types+1, k);
3559 s[k] = 0;
3560
3561 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3562 if (r <= 0)
3563 return r;
3564
3565 for (;;) {
3566 r = sd_bus_message_skip(m, s);
3567 if (r < 0)
3568 return r;
3569 if (r == 0)
3570 break;
3571 }
3572
3573 r = sd_bus_message_exit_container(m);
3574 if (r < 0)
3575 return r;
3576 }
3577
3578 r = sd_bus_message_skip(m, types + 1 + k);
3579 if (r < 0)
3580 return r;
3581
3582 return 1;
3583 }
3584
3585 case SD_BUS_TYPE_VARIANT: {
3586 const char *contents;
3587 char x;
3588
3589 r = sd_bus_message_peek_type(m, &x, &contents);
3590 if (r <= 0)
3591 return r;
3592
3593 if (x != SD_BUS_TYPE_VARIANT)
3594 return -ENXIO;
3595
3596 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
3597 if (r <= 0)
3598 return r;
3599
3600 r = sd_bus_message_skip(m, contents);
3601 if (r < 0)
3602 return r;
3603 assert(r != 0);
3604
3605 r = sd_bus_message_exit_container(m);
3606 if (r < 0)
3607 return r;
3608
3609 r = sd_bus_message_skip(m, types + 1);
3610 if (r < 0)
3611 return r;
3612
3613 return 1;
3614 }
3615
3616 case SD_BUS_TYPE_STRUCT_BEGIN:
3617 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3618 size_t k;
3619
3620 r = signature_element_length(types, &k);
3621 if (r < 0)
3622 return r;
3623
3624 {
3625 char s[k-1];
3626 memcpy(s, types+1, k-2);
3627 s[k-2] = 0;
3628
3629 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3630 if (r <= 0)
3631 return r;
3632
3633 r = sd_bus_message_skip(m, s);
3634 if (r < 0)
3635 return r;
9b07511d
LP
3636
3637 r = sd_bus_message_exit_container(m);
3638 if (r < 0)
3639 return r;
3640 }
3641
3642 r = sd_bus_message_skip(m, types + k);
3643 if (r < 0)
3644 return r;
3645
3646 return 1;
3647 }
3648
3649 default:
3650 return -EINVAL;
3651 }
3652}
3653
2ac7c17f
LP
3654_public_ int sd_bus_message_read_array(
3655 sd_bus_message *m,
3656 char type,
3657 const void **ptr,
3658 size_t *size) {
3659
b3af9646
LP
3660 struct bus_container *c;
3661 void *p;
3662 size_t sz;
3663 ssize_t align;
3664 int r;
3665
9d6c7c82
LP
3666 assert_return(m, -EINVAL);
3667 assert_return(m->sealed, -EPERM);
3668 assert_return(bus_type_is_trivial(type), -EINVAL);
3669 assert_return(ptr, -EINVAL);
3670 assert_return(size, -EINVAL);
15411c0c 3671 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
b3af9646 3672
b3af9646 3673 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
6293d958 3674 if (r < 0)
b3af9646 3675 return r;
6293d958
LP
3676 if (r == 0) {
3677 *ptr = NULL;
3678 *size = 0;
3679 return 0;
3680 }
b3af9646 3681
9c65778d 3682 c = message_get_last_container(m);
6647dc66 3683
0dd48768
YW
3684 align = bus_type_get_alignment(type);
3685 if (align < 0)
3686 return align;
6647dc66 3687
0dd48768 3688 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
b3af9646 3689
5e86fd7b
LP
3690 if (sz == 0)
3691 /* Zero length array, let's return some aligned
3692 * pointer that is not NULL */
0241c1c0 3693 p = (uint8_t*) align;
5e86fd7b
LP
3694 else {
3695 r = message_peek_body(m, &m->rindex, align, sz, &p);
3696 if (r < 0)
3697 goto fail;
b3af9646
LP
3698 }
3699
3700 r = sd_bus_message_exit_container(m);
3701 if (r < 0)
3702 goto fail;
3703
3704 *ptr = (const void*) p;
3705 *size = sz;
3706
3707 return 1;
3708
3709fail:
3710 message_quit_container(m);
3711 return r;
3712}
3713
80a46c73
LP
3714static int message_peek_fields(
3715 sd_bus_message *m,
3716 size_t *rindex,
3717 size_t align,
3718 size_t nbytes,
3719 void **ret) {
3720
c0f664ca
YW
3721 size_t start, end;
3722
80a46c73
LP
3723 assert(m);
3724 assert(rindex);
3725 assert(align > 0);
3726
c0f664ca
YW
3727 start = ALIGN_TO(*rindex, align);
3728 if (start > m->fields_size)
3729 return -EBADMSG;
3730
3731 /* Avoid overflow below */
3732 if (nbytes > SIZE_MAX - start)
3733 return -EBADMSG;
3734
3735 end = start + nbytes;
3736 if (end > m->fields_size)
3737 return -EBADMSG;
3738
3739 /* Verify that padding is 0 */
3740 uint8_t *p = BUS_MESSAGE_FIELDS(m);
3741 for (size_t k = *rindex; k < start; k++)
3742 if (p[k] != 0)
3743 return -EBADMSG;
3744
3745 if (ret)
3746 *ret = p + start;
3747
3748 *rindex = end;
3749 return 1;
80a46c73
LP
3750}
3751
9f26c90c
LP
3752static int message_peek_field_uint32(
3753 sd_bus_message *m,
3754 size_t *ri,
6647dc66 3755 size_t item_size,
9f26c90c
LP
3756 uint32_t *ret) {
3757
3758 int r;
3759 void *q;
3760
3761 assert(m);
3762 assert(ri);
3763
3764 r = message_peek_fields(m, ri, 4, 4, &q);
3765 if (r < 0)
3766 return r;
3767
3768 if (ret)
3769 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3770
3771 return 0;
3772}
3773
80a46c73
LP
3774static int message_peek_field_string(
3775 sd_bus_message *m,
6693860f 3776 bool (*validate)(const char *p),
80a46c73 3777 size_t *ri,
6647dc66 3778 size_t item_size,
80a46c73
LP
3779 const char **ret) {
3780
9f26c90c 3781 uint32_t l;
80a46c73
LP
3782 int r;
3783 void *q;
3784
9a17484d 3785 assert(m);
80a46c73
LP
3786 assert(ri);
3787
0dd48768
YW
3788 r = message_peek_field_uint32(m, ri, 4, &l);
3789 if (r < 0)
3790 return r;
6647dc66 3791
0dd48768
YW
3792 if (l == UINT32_MAX)
3793 /* avoid overflow right below */
3794 return -EBADMSG;
902000c1 3795
0dd48768
YW
3796 r = message_peek_fields(m, ri, 1, l+1, &q);
3797 if (r < 0)
3798 return r;
9a17484d 3799
6693860f
LP
3800 if (validate) {
3801 if (!validate_nul(q, l))
3802 return -EBADMSG;
3803
3804 if (!validate(q))
ac89bf1d
LP
3805 return -EBADMSG;
3806 } else {
3807 if (!validate_string(q, l))
3808 return -EBADMSG;
3809 }
80a46c73
LP
3810
3811 if (ret)
3812 *ret = q;
3813
3814 return 0;
3815}
3816
3817static int message_peek_field_signature(
3818 sd_bus_message *m,
3819 size_t *ri,
6647dc66 3820 size_t item_size,
80a46c73
LP
3821 const char **ret) {
3822
3823 size_t l;
3824 int r;
3825 void *q;
3826
3827 assert(m);
3828 assert(ri);
3829
0dd48768
YW
3830 r = message_peek_fields(m, ri, 1, 1, &q);
3831 if (r < 0)
3832 return r;
6647dc66 3833
0dd48768
YW
3834 l = *(uint8_t*) q;
3835 if (l == UINT8_MAX)
3836 /* avoid overflow right below */
3837 return -EBADMSG;
902000c1 3838
0dd48768
YW
3839 r = message_peek_fields(m, ri, 1, l+1, &q);
3840 if (r < 0)
3841 return r;
80a46c73
LP
3842
3843 if (!validate_signature(q, l))
3844 return -EBADMSG;
3845
3846 if (ret)
3847 *ret = q;
3848
3849 return 0;
3850}
3851
80a46c73
LP
3852static int message_skip_fields(
3853 sd_bus_message *m,
3854 size_t *ri,
3855 uint32_t array_size,
3856 const char **signature) {
3857
3858 size_t original_index;
3859 int r;
3860
3861 assert(m);
3862 assert(ri);
3863 assert(signature);
3864
3865 original_index = *ri;
3866
3867 for (;;) {
3868 char t;
80a46c73
LP
3869 size_t l;
3870
f5fbe71d 3871 if (array_size != UINT32_MAX &&
80a46c73
LP
3872 array_size <= *ri - original_index)
3873 return 0;
3874
3875 t = **signature;
3876 if (!t)
3877 return 0;
3878
6693860f
LP
3879 if (t == SD_BUS_TYPE_STRING) {
3880
6647dc66 3881 r = message_peek_field_string(m, NULL, ri, 0, NULL);
6693860f
LP
3882 if (r < 0)
3883 return r;
3884
3885 (*signature)++;
3886
3887 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 3888
6647dc66 3889 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
80a46c73
LP
3890 if (r < 0)
3891 return r;
3892
3893 (*signature)++;
3894
3895 } else if (t == SD_BUS_TYPE_SIGNATURE) {
3896
6647dc66 3897 r = message_peek_field_signature(m, ri, 0, NULL);
80a46c73
LP
3898 if (r < 0)
3899 return r;
3900
3901 (*signature)++;
3902
3903 } else if (bus_type_is_basic(t)) {
27f6e5c7 3904 ssize_t align, k;
80a46c73 3905
c66a2e0c
TG
3906 align = bus_type_get_alignment(t);
3907 k = bus_type_get_size(t);
27f6e5c7 3908 assert(align > 0 && k > 0);
80a46c73
LP
3909
3910 r = message_peek_fields(m, ri, align, k, NULL);
3911 if (r < 0)
3912 return r;
9a17484d 3913
80a46c73
LP
3914 (*signature)++;
3915
3916 } else if (t == SD_BUS_TYPE_ARRAY) {
3917
73777ddb 3918 r = signature_element_length(*signature + 1, &l);
80a46c73
LP
3919 if (r < 0)
3920 return r;
3921
3922 assert(l >= 1);
3923 {
73777ddb 3924 char sig[l + 1], *s = sig;
9f26c90c 3925 uint32_t nas;
80a46c73
LP
3926 int alignment;
3927
73777ddb
ZJS
3928 strncpy(sig, *signature + 1, l);
3929 sig[l] = '\0';
80a46c73
LP
3930
3931 alignment = bus_type_get_alignment(sig[0]);
3932 if (alignment < 0)
3933 return alignment;
3934
6647dc66 3935 r = message_peek_field_uint32(m, ri, 0, &nas);
80a46c73
LP
3936 if (r < 0)
3937 return r;
ac89bf1d 3938 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
3939 return -EBADMSG;
3940
3941 r = message_peek_fields(m, ri, alignment, 0, NULL);
3942 if (r < 0)
3943 return r;
3944
3945 r = message_skip_fields(m, ri, nas, (const char**) &s);
3946 if (r < 0)
3947 return r;
3948 }
3949
3950 (*signature) += 1 + l;
3951
3952 } else if (t == SD_BUS_TYPE_VARIANT) {
3953 const char *s;
3954
6647dc66 3955 r = message_peek_field_signature(m, ri, 0, &s);
80a46c73
LP
3956 if (r < 0)
3957 return r;
3958
f5fbe71d 3959 r = message_skip_fields(m, ri, UINT32_MAX, (const char**) &s);
80a46c73
LP
3960 if (r < 0)
3961 return r;
3962
3963 (*signature)++;
3964
945c2931 3965 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
80a46c73
LP
3966
3967 r = signature_element_length(*signature, &l);
3968 if (r < 0)
3969 return r;
3970
3971 assert(l >= 2);
3972 {
3d338a30
ZJS
3973 char sig[l + 1], *s = sig;
3974 strncpy(sig, *signature + 1, l);
3975 sig[l] = '\0';
80a46c73 3976
f5fbe71d 3977 r = message_skip_fields(m, ri, UINT32_MAX, (const char**) &s);
80a46c73
LP
3978 if (r < 0)
3979 return r;
3980 }
3981
3982 *signature += l;
3983 } else
d831fb6f 3984 return -EBADMSG;
80a46c73
LP
3985 }
3986}
3987
75c85c3b 3988static int message_parse_fields(sd_bus_message *m) {
2c93b4ef 3989 uint32_t unix_fds = 0;
5a4d665a 3990 bool unix_fds_set = false;
0dd48768 3991 int r;
80a46c73
LP
3992
3993 assert(m);
3994
0dd48768 3995 m->user_body_size = m->body_size;
6647dc66 3996
0dd48768 3997 for (size_t ri = 0; ri < m->fields_size; ) {
80a46c73 3998 const char *signature;
2ac7c17f 3999 uint64_t field_type;
f5fbe71d 4000 size_t item_size = SIZE_MAX;
0dd48768 4001 uint8_t *u8;
6647dc66 4002
0dd48768
YW
4003 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
4004 if (r < 0)
4005 return r;
6647dc66 4006
0dd48768 4007 field_type = *u8;
6647dc66 4008
0dd48768
YW
4009 r = message_peek_field_signature(m, &ri, 0, &signature);
4010 if (r < 0)
4011 return r;
80a46c73 4012
2ac7c17f
LP
4013 switch (field_type) {
4014
0461f8cd 4015 case _BUS_MESSAGE_HEADER_INVALID:
80a46c73
LP
4016 return -EBADMSG;
4017
0461f8cd 4018 case BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
4019
4020 if (m->path)
4021 return -EBADMSG;
4022
80a46c73
LP
4023 if (!streq(signature, "o"))
4024 return -EBADMSG;
4025
6647dc66 4026 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
80a46c73
LP
4027 break;
4028
0461f8cd 4029 case BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
4030
4031 if (m->interface)
4032 return -EBADMSG;
4033
80a46c73
LP
4034 if (!streq(signature, "s"))
4035 return -EBADMSG;
4036
6647dc66 4037 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
80a46c73
LP
4038 break;
4039
0461f8cd 4040 case BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
4041
4042 if (m->member)
4043 return -EBADMSG;
4044
80a46c73
LP
4045 if (!streq(signature, "s"))
4046 return -EBADMSG;
4047
6647dc66 4048 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
80a46c73
LP
4049 break;
4050
0461f8cd 4051 case BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
4052
4053 if (m->error.name)
4054 return -EBADMSG;
4055
80a46c73
LP
4056 if (!streq(signature, "s"))
4057 return -EBADMSG;
4058
6647dc66 4059 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
79f8d3d2
LP
4060 if (r >= 0)
4061 m->error._need_free = -1;
4062
80a46c73
LP
4063 break;
4064
0461f8cd 4065 case BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
4066
4067 if (m->destination)
4068 return -EBADMSG;
4069
80a46c73
LP
4070 if (!streq(signature, "s"))
4071 return -EBADMSG;
4072
6647dc66 4073 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
80a46c73
LP
4074 break;
4075
0461f8cd 4076 case BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
4077
4078 if (m->sender)
4079 return -EBADMSG;
4080
80a46c73
LP
4081 if (!streq(signature, "s"))
4082 return -EBADMSG;
4083
6647dc66 4084 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
49b832c5 4085
a132bef0 4086 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
49b832c5
LP
4087 m->creds.unique_name = (char*) m->sender;
4088 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
4089 }
4090
80a46c73
LP
4091 break;
4092
0461f8cd 4093 case BUS_MESSAGE_HEADER_SIGNATURE: {
80a46c73
LP
4094 const char *s;
4095 char *c;
4096
2c93b4ef
LP
4097 if (m->root_container.signature)
4098 return -EBADMSG;
4099
80a46c73
LP
4100 if (!streq(signature, "g"))
4101 return -EBADMSG;
4102
6647dc66 4103 r = message_peek_field_signature(m, &ri, item_size, &s);
80a46c73
LP
4104 if (r < 0)
4105 return r;
4106
4107 c = strdup(s);
4108 if (!c)
4109 return -ENOMEM;
4110
7a4b8512 4111 free_and_replace(m->root_container.signature, c);
80a46c73
LP
4112 break;
4113 }
4114
0dd48768
YW
4115 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
4116 uint32_t serial;
42c4ebcb 4117
693eb9a2 4118 if (m->reply_cookie != 0)
2c93b4ef
LP
4119 return -EBADMSG;
4120
2ac7c17f 4121
0dd48768
YW
4122 if (!streq(signature, "u"))
4123 return -EBADMSG;
b381de41 4124
0dd48768
YW
4125 r = message_peek_field_uint32(m, &ri, item_size, &serial);
4126 if (r < 0)
4127 return r;
2ac7c17f 4128
0dd48768 4129 m->reply_cookie = serial;
42c4ebcb 4130
693eb9a2 4131 if (m->reply_cookie == 0)
6693860f
LP
4132 return -EBADMSG;
4133
80a46c73 4134 break;
0dd48768 4135 }
0461f8cd 4136 case BUS_MESSAGE_HEADER_UNIX_FDS:
5a4d665a 4137 if (unix_fds_set)
2c93b4ef
LP
4138 return -EBADMSG;
4139
4140 if (!streq(signature, "u"))
4141 return -EBADMSG;
4142
6647dc66 4143 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
2c93b4ef
LP
4144 if (r < 0)
4145 return -EBADMSG;
4146
5a4d665a 4147 unix_fds_set = true;
2c93b4ef
LP
4148 break;
4149
80a46c73 4150 default:
0dd48768 4151 r = message_skip_fields(m, &ri, UINT32_MAX, (const char **) &signature);
80a46c73 4152 }
80a46c73
LP
4153 if (r < 0)
4154 return r;
4155 }
4156
2c93b4ef
LP
4157 if (m->n_fds != unix_fds)
4158 return -EBADMSG;
4159
80a46c73
LP
4160 switch (m->header->type) {
4161
40ca29a1 4162 case SD_BUS_MESSAGE_SIGNAL:
80a46c73
LP
4163 if (!m->path || !m->interface || !m->member)
4164 return -EBADMSG;
7fa934b0
LP
4165
4166 if (m->reply_cookie != 0)
4167 return -EBADMSG;
4168
80a46c73
LP
4169 break;
4170
40ca29a1 4171 case SD_BUS_MESSAGE_METHOD_CALL:
80a46c73
LP
4172
4173 if (!m->path || !m->member)
4174 return -EBADMSG;
4175
7fa934b0
LP
4176 if (m->reply_cookie != 0)
4177 return -EBADMSG;
4178
80a46c73
LP
4179 break;
4180
40ca29a1 4181 case SD_BUS_MESSAGE_METHOD_RETURN:
80a46c73 4182
693eb9a2 4183 if (m->reply_cookie == 0)
80a46c73
LP
4184 return -EBADMSG;
4185 break;
4186
40ca29a1 4187 case SD_BUS_MESSAGE_METHOD_ERROR:
80a46c73 4188
693eb9a2 4189 if (m->reply_cookie == 0 || !m->error.name)
80a46c73
LP
4190 return -EBADMSG;
4191 break;
4192 }
9a17484d 4193
35473296
LP
4194 /* Refuse non-local messages that claim they are local */
4195 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
4196 return -EBADMSG;
4197 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
4198 return -EBADMSG;
4199 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
4200 return -EBADMSG;
4201
2ac7c17f 4202 m->root_container.end = m->user_body_size;
6647dc66 4203
89ffcd2a 4204 /* Try to read the error message, but if we can't it's a non-issue */
40ca29a1 4205 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
d3839740 4206 (void) sd_bus_message_read(m, "s", &m->error.message);
89ffcd2a 4207
9a17484d
LP
4208 return 0;
4209}
4210
d9f644e2 4211_public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
9d6c7c82
LP
4212 assert_return(m, -EINVAL);
4213 assert_return(destination, -EINVAL);
3d51a011 4214 assert_return(service_name_is_valid(destination), -EINVAL);
9d6c7c82
LP
4215 assert_return(!m->sealed, -EPERM);
4216 assert_return(!m->destination, -EEXIST);
9a17484d 4217
0461f8cd 4218 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
9a17484d
LP
4219}
4220
48ef41a3
LP
4221_public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
4222 assert_return(m, -EINVAL);
4223 assert_return(sender, -EINVAL);
3d51a011 4224 assert_return(service_name_is_valid(sender), -EINVAL);
48ef41a3
LP
4225 assert_return(!m->sealed, -EPERM);
4226 assert_return(!m->sender, -EEXIST);
4227
4228 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
4229}
4230
de1c301e
LP
4231int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
4232 size_t total;
de1c301e 4233 void *p, *e;
da6053d0 4234 size_t i;
bc7fd8cd 4235 struct bus_body_part *part;
de1c301e
LP
4236
4237 assert(m);
4238 assert(buffer);
4239 assert(sz);
4240
6629161f 4241 total = BUS_MESSAGE_SIZE(m);
de1c301e
LP
4242
4243 p = malloc(total);
4244 if (!p)
4245 return -ENOMEM;
4246
c91cb83c 4247 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
9b29bb68 4248 MESSAGE_FOREACH_PART(part, i, m)
bc7fd8cd 4249 e = mempcpy(e, part->data, part->size);
2100fa10
LP
4250
4251 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
4252
4253 *buffer = p;
4254 *sz = total;
4255
4256 return 0;
4257}
89ffcd2a
LP
4258
4259int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
63ab06c4
ZJS
4260 char type;
4261 const char *contents, *s;
89ffcd2a
LP
4262 int r;
4263
4264 assert(m);
4265 assert(l);
4266
63ab06c4
ZJS
4267 r = sd_bus_message_peek_type(m, &type, &contents);
4268 if (r < 0)
4269 return r;
4270
4271 if (type != SD_BUS_TYPE_ARRAY || !STR_IN_SET(contents, "s", "o", "g"))
4272 return -ENXIO;
4273
4274 r = sd_bus_message_enter_container(m, 'a', NULL);
4686d1b6 4275 if (r <= 0)
89ffcd2a
LP
4276 return r;
4277
63ab06c4
ZJS
4278 /* sd_bus_message_read_basic() does content validation for us. */
4279 while ((r = sd_bus_message_read_basic(m, *contents, &s)) > 0) {
89ffcd2a
LP
4280 r = strv_extend(l, s);
4281 if (r < 0)
4282 return r;
4283 }
43ef7603
DH
4284 if (r < 0)
4285 return r;
89ffcd2a
LP
4286
4287 r = sd_bus_message_exit_container(m);
4288 if (r < 0)
4289 return r;
4290
405cd3aa 4291 return 1;
89ffcd2a 4292}
392d5b37 4293
ba341e7c 4294_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
7a4b8512 4295 _cleanup_strv_free_ char **strv = NULL;
4686d1b6
MAP
4296 int r;
4297
4298 assert_return(m, -EINVAL);
4299 assert_return(m->sealed, -EPERM);
4300 assert_return(l, -EINVAL);
4301
4302 r = bus_message_read_strv_extend(m, &strv);
7a4b8512 4303 if (r <= 0)
4686d1b6 4304 return r;
4686d1b6 4305
7a4b8512 4306 *l = TAKE_PTR(strv);
4686d1b6
MAP
4307 return 1;
4308}
4309
eccd47c5
LP
4310static int bus_message_get_arg_skip(
4311 sd_bus_message *m,
4312 unsigned i,
4313 char *_type,
4314 const char **_contents) {
4315
42c5aaf3 4316 unsigned j;
198b158f 4317 int r;
392d5b37 4318
392d5b37
LP
4319 r = sd_bus_message_rewind(m, true);
4320 if (r < 0)
198b158f 4321 return r;
392d5b37 4322
198b158f 4323 for (j = 0;; j++) {
eccd47c5
LP
4324 const char *contents;
4325 char type;
4326
198b158f
LP
4327 r = sd_bus_message_peek_type(m, &type, &contents);
4328 if (r < 0)
4329 return r;
4330 if (r == 0)
4331 return -ENXIO;
4332
4333 /* Don't match against arguments after the first one we don't understand */
4334 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
4335 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
4336 return -ENXIO;
42c5aaf3 4337
eccd47c5
LP
4338 if (j >= i) {
4339 if (_contents)
4340 *_contents = contents;
4341 if (_type)
4342 *_type = type;
4343 return 0;
4344 }
198b158f
LP
4345
4346 r = sd_bus_message_skip(m, NULL);
392d5b37 4347 if (r < 0)
198b158f
LP
4348 return r;
4349 }
392d5b37 4350
eccd47c5 4351}
392d5b37 4352
eccd47c5
LP
4353int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
4354 char type;
4355 int r;
198b158f 4356
eccd47c5
LP
4357 assert(m);
4358 assert(str);
198b158f 4359
eccd47c5
LP
4360 r = bus_message_get_arg_skip(m, i, &type, NULL);
4361 if (r < 0)
4362 return r;
198b158f 4363
eccd47c5
LP
4364 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
4365 return -ENXIO;
392d5b37 4366
eccd47c5
LP
4367 return sd_bus_message_read_basic(m, type, str);
4368}
4369
4370int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
4371 const char *contents;
4372 char type;
4373 int r;
4374
4375 assert(m);
4376 assert(strv);
4377
4378 r = bus_message_get_arg_skip(m, i, &type, &contents);
4379 if (r < 0)
4380 return r;
4381
4382 if (type != SD_BUS_TYPE_ARRAY)
4383 return -ENXIO;
4384 if (!STR_IN_SET(contents, "s", "o", "g"))
4385 return -ENXIO;
4386
4387 return sd_bus_message_read_strv(m, strv);
392d5b37 4388}
2100fa10 4389
d9f644e2 4390_public_ int sd_bus_message_get_errno(sd_bus_message *m) {
b49ffb29 4391 assert_return(m, EINVAL);
eb01ba5d 4392
40ca29a1 4393 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
eb01ba5d
LP
4394 return 0;
4395
40ca29a1 4396 return sd_bus_error_get_errno(&m->error);
eb01ba5d 4397}
29ddb38f 4398
d9f644e2 4399_public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
29ddb38f
LP
4400 struct bus_container *c;
4401
9d6c7c82 4402 assert_return(m, NULL);
29ddb38f 4403
9c65778d 4404 c = complete ? &m->root_container : message_get_last_container(m);
d6385068 4405 return strempty(c->signature);
29ddb38f 4406}
c430fee6 4407
8022212b
LP
4408_public_ int sd_bus_message_is_empty(sd_bus_message *m) {
4409 assert_return(m, -EINVAL);
4410
4411 return isempty(m->root_container.signature);
4412}
4413
64e96a19
LP
4414_public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
4415 assert_return(m, -EINVAL);
4416
4417 return streq(strempty(m->root_container.signature), strempty(signature));
4418}
4419
d9f644e2 4420_public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
c430fee6
LP
4421 bool done_something = false;
4422 int r;
4423
80ba3b84
LP
4424 assert_return(m, -EINVAL);
4425 assert_return(source, -EINVAL);
4426 assert_return(!m->sealed, -EPERM);
4427 assert_return(source->sealed, -EPERM);
4428
c430fee6
LP
4429 do {
4430 const char *contents;
4431 char type;
4432 union {
4433 uint8_t u8;
4434 uint16_t u16;
4435 int16_t s16;
4436 uint32_t u32;
4437 int32_t s32;
4438 uint64_t u64;
4439 int64_t s64;
4440 double d64;
4441 const char *string;
4442 int i;
4443 } basic;
4444
4445 r = sd_bus_message_peek_type(source, &type, &contents);
4446 if (r < 0)
4447 return r;
4448 if (r == 0)
4449 break;
4450
4451 done_something = true;
4452
4453 if (bus_type_is_container(type) > 0) {
4454
4455 r = sd_bus_message_enter_container(source, type, contents);
4456 if (r < 0)
4457 return r;
4458
4459 r = sd_bus_message_open_container(m, type, contents);
4460 if (r < 0)
4461 return r;
4462
4463 r = sd_bus_message_copy(m, source, true);
4464 if (r < 0)
4465 return r;
4466
4467 r = sd_bus_message_close_container(m);
4468 if (r < 0)
4469 return r;
4470
4471 r = sd_bus_message_exit_container(source);
4472 if (r < 0)
4473 return r;
4474
4475 continue;
4476 }
4477
4478 r = sd_bus_message_read_basic(source, type, &basic);
4479 if (r < 0)
4480 return r;
4481
4482 assert(r > 0);
4483
945c2931 4484 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
c430fee6
LP
4485 r = sd_bus_message_append_basic(m, type, basic.string);
4486 else
4487 r = sd_bus_message_append_basic(m, type, &basic);
4488
4489 if (r < 0)
4490 return r;
4491
4492 } while (all);
4493
4494 return done_something;
4495}
4496
d9f644e2 4497_public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
c430fee6
LP
4498 const char *c;
4499 char t;
4500 int r;
4501
4502 assert_return(m, -EINVAL);
4503 assert_return(m->sealed, -EPERM);
4504 assert_return(!type || bus_type_is_valid(type), -EINVAL);
4505 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
4506 assert_return(type || contents, -EINVAL);
4507 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
4508
4509 r = sd_bus_message_peek_type(m, &t, &c);
4510 if (r <= 0)
4511 return r;
4512
4513 if (type != 0 && type != t)
4514 return 0;
4515
4516 if (contents && !streq_ptr(contents, c))
4517 return 0;
4518
4519 return 1;
4520}
2be44176
LP
4521
4522_public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
4523 assert_return(m, NULL);
4524
4525 return m->bus;
4526}
e1c433c6
LP
4527
4528int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
4afd3348 4529 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
e1c433c6
LP
4530 usec_t timeout;
4531 int r;
4532
4533 assert(bus);
4534 assert(m);
4535 assert(*m);
4536
4537 switch ((*m)->header->type) {
4538
4539 case SD_BUS_MESSAGE_SIGNAL:
151b9b96 4540 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
e1c433c6
LP
4541 if (r < 0)
4542 return r;
4543
4544 break;
4545
4546 case SD_BUS_MESSAGE_METHOD_CALL:
151b9b96 4547 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
e1c433c6
LP
4548 if (r < 0)
4549 return r;
4550
4551 break;
4552
4553 case SD_BUS_MESSAGE_METHOD_RETURN:
4554 case SD_BUS_MESSAGE_METHOD_ERROR:
4555
75bcbcf2
SA
4556 r = sd_bus_message_new(bus, &n, (*m)->header->type);
4557 if (r < 0)
e1c433c6
LP
4558 return -ENOMEM;
4559
75bcbcf2
SA
4560 assert(n);
4561
693eb9a2 4562 n->reply_cookie = (*m)->reply_cookie;
b267a6d2
LP
4563
4564 r = message_append_reply_cookie(n, n->reply_cookie);
e1c433c6
LP
4565 if (r < 0)
4566 return r;
4567
4568 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
4569 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
4570 if (r < 0)
4571 return r;
4572
4573 n->error._need_free = -1;
4574 }
4575
4576 break;
4577
4578 default:
4579 return -EINVAL;
4580 }
4581
4582 if ((*m)->destination && !n->destination) {
4583 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
4584 if (r < 0)
4585 return r;
4586 }
4587
4588 if ((*m)->sender && !n->sender) {
4589 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
4590 if (r < 0)
4591 return r;
4592 }
4593
4594 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
4595
4596 r = sd_bus_message_copy(n, *m, true);
4597 if (r < 0)
4598 return r;
4599
4600 timeout = (*m)->timeout;
385b2eb2
YW
4601 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) {
4602 r = sd_bus_get_method_call_timeout(bus, &timeout);
4603 if (r < 0)
4604 return r;
4605 }
e1c433c6 4606
75bcbcf2 4607 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
e1c433c6
LP
4608 if (r < 0)
4609 return r;
4610
4611 sd_bus_message_unref(*m);
1cc6c93a 4612 *m = TAKE_PTR(n);
e1c433c6
LP
4613
4614 return 0;
4615}
a7639e37 4616
ca7b42c8 4617_public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
c3362c2f
ZJS
4618 static bool warned = false;
4619
ca7b42c8
LP
4620 assert_return(m, -EINVAL);
4621 assert_return(priority, -EINVAL);
4622
c3362c2f
ZJS
4623 if (!warned) {
4624 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
4625 warned = true;
4626 }
4627
4628 *priority = 0;
ca7b42c8
LP
4629 return 0;
4630}
4631
4632_public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
c3362c2f
ZJS
4633 static bool warned = false;
4634
ca7b42c8
LP
4635 assert_return(m, -EINVAL);
4636 assert_return(!m->sealed, -EPERM);
4637
c3362c2f
ZJS
4638 if (!warned) {
4639 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
4640 warned = true;
4641 }
4642
ca7b42c8
LP
4643 return 0;
4644}
7a77d2a4
LP
4645
4646_public_ int sd_bus_message_sensitive(sd_bus_message *m) {
4647 assert_return(m, -EINVAL);
4648
4649 m->sensitive = true;
4650 return 0;
4651}