]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-message.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-message.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6
7 #include "sd-bus.h"
8
9 #include "alloc-util.h"
10 #include "bus-gvariant.h"
11 #include "bus-internal.h"
12 #include "bus-message.h"
13 #include "bus-signature.h"
14 #include "bus-type.h"
15 #include "bus-util.h"
16 #include "fd-util.h"
17 #include "io-util.h"
18 #include "memfd-util.h"
19 #include "string-util.h"
20 #include "strv.h"
21 #include "time-util.h"
22 #include "utf8.h"
23 #include "util.h"
24
25 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
26
27 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
28
29 if (p == NULL)
30 return NULL;
31
32 if (old_base == new_base)
33 return (void*) p;
34
35 if ((uint8_t*) p < (uint8_t*) old_base)
36 return (void*) p;
37
38 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
39 return (void*) p;
40
41 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
42 }
43
44 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
45 assert(m);
46 assert(part);
47
48 if (part->memfd >= 0)
49 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
50 else if (part->munmap_this)
51 munmap(part->mmap_begin, part->mapped);
52 else if (part->free_this)
53 free(part->data);
54
55 if (part != &m->body)
56 free(part);
57 }
58
59 static void message_reset_parts(sd_bus_message *m) {
60 struct bus_body_part *part;
61
62 assert(m);
63
64 part = &m->body;
65 while (m->n_body_parts > 0) {
66 struct bus_body_part *next = part->next;
67 message_free_part(m, part);
68 part = next;
69 m->n_body_parts--;
70 }
71
72 m->body_end = NULL;
73
74 m->cached_rindex_part = NULL;
75 m->cached_rindex_part_begin = 0;
76 }
77
78 static struct bus_container *message_get_last_container(sd_bus_message *m) {
79 assert(m);
80
81 if (m->n_containers == 0)
82 return &m->root_container;
83
84 assert(m->containers);
85 return m->containers + m->n_containers - 1;
86 }
87
88 static void message_free_last_container(sd_bus_message *m) {
89 struct bus_container *c;
90
91 c = message_get_last_container(m);
92
93 free(c->signature);
94 free(c->peeked_signature);
95 free(c->offsets);
96
97 /* Move to previous container, but not if we are on root container */
98 if (m->n_containers > 0)
99 m->n_containers--;
100 }
101
102 static void message_reset_containers(sd_bus_message *m) {
103 assert(m);
104
105 while (m->n_containers > 0)
106 message_free_last_container(m);
107
108 m->containers = mfree(m->containers);
109 m->containers_allocated = 0;
110 m->root_container.index = 0;
111 }
112
113 static sd_bus_message* message_free(sd_bus_message *m) {
114 assert(m);
115
116 if (m->free_header)
117 free(m->header);
118
119 message_reset_parts(m);
120
121 sd_bus_unref(m->bus);
122
123 if (m->free_fds) {
124 close_many(m->fds, m->n_fds);
125 free(m->fds);
126 }
127
128 if (m->iovec != m->iovec_fixed)
129 free(m->iovec);
130
131 message_reset_containers(m);
132 assert(m->n_containers == 0);
133 message_free_last_container(m);
134
135 bus_creds_done(&m->creds);
136 return mfree(m);
137 }
138
139 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
140
141 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
142 void *op, *np;
143 size_t old_size, new_size, start;
144
145 assert(m);
146
147 if (m->poisoned)
148 return NULL;
149
150 old_size = sizeof(struct bus_header) + m->fields_size;
151 start = ALIGN_TO(old_size, align);
152 new_size = start + sz;
153
154 if (new_size < start ||
155 new_size > (size_t) ((uint32_t) -1))
156 goto poison;
157
158 if (old_size == new_size)
159 return (uint8_t*) m->header + old_size;
160
161 if (m->free_header) {
162 np = realloc(m->header, ALIGN8(new_size));
163 if (!np)
164 goto poison;
165 } else {
166 /* Initially, the header is allocated as part of
167 * the sd_bus_message itself, let's replace it by
168 * dynamic data */
169
170 np = malloc(ALIGN8(new_size));
171 if (!np)
172 goto poison;
173
174 memcpy(np, m->header, sizeof(struct bus_header));
175 }
176
177 /* Zero out padding */
178 if (start > old_size)
179 memzero((uint8_t*) np + old_size, start - old_size);
180
181 op = m->header;
182 m->header = np;
183 m->fields_size = new_size - sizeof(struct bus_header);
184
185 /* Adjust quick access pointers */
186 m->path = adjust_pointer(m->path, op, old_size, m->header);
187 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
188 m->member = adjust_pointer(m->member, op, old_size, m->header);
189 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
190 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
191 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
192
193 m->free_header = true;
194
195 if (add_offset) {
196 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
197 goto poison;
198
199 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
200 }
201
202 return (uint8_t*) np + start;
203
204 poison:
205 m->poisoned = true;
206 return NULL;
207 }
208
209 static int message_append_field_string(
210 sd_bus_message *m,
211 uint64_t h,
212 char type,
213 const char *s,
214 const char **ret) {
215
216 size_t l;
217 uint8_t *p;
218
219 assert(m);
220
221 /* dbus1 only allows 8bit header field ids */
222 if (h > 0xFF)
223 return -EINVAL;
224
225 /* dbus1 doesn't allow strings over 32bit, let's enforce this
226 * globally, to not risk convertability */
227 l = strlen(s);
228 if (l > UINT32_MAX)
229 return -EINVAL;
230
231 /* Signature "(yv)" where the variant contains "s" */
232
233 if (BUS_MESSAGE_IS_GVARIANT(m)) {
234
235 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
236 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
237 if (!p)
238 return -ENOMEM;
239
240 *((uint64_t*) p) = h;
241 memcpy(p+8, s, l);
242 p[8+l] = 0;
243 p[8+l+1] = 0;
244 p[8+l+2] = type;
245
246 if (ret)
247 *ret = (char*) p + 8;
248
249 } else {
250 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
251 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
252 if (!p)
253 return -ENOMEM;
254
255 p[0] = (uint8_t) h;
256 p[1] = 1;
257 p[2] = type;
258 p[3] = 0;
259
260 ((uint32_t*) p)[1] = l;
261 memcpy(p + 8, s, l + 1);
262
263 if (ret)
264 *ret = (char*) p + 8;
265 }
266
267 return 0;
268 }
269
270 static int message_append_field_signature(
271 sd_bus_message *m,
272 uint64_t h,
273 const char *s,
274 const char **ret) {
275
276 size_t l;
277 uint8_t *p;
278
279 assert(m);
280
281 /* dbus1 only allows 8bit header field ids */
282 if (h > 0xFF)
283 return -EINVAL;
284
285 /* dbus1 doesn't allow signatures over 8bit, let's enforce
286 * this globally, to not risk convertability */
287 l = strlen(s);
288 if (l > 255)
289 return -EINVAL;
290
291 /* Signature "(yv)" where the variant contains "g" */
292
293 if (BUS_MESSAGE_IS_GVARIANT(m))
294 /* For gvariant the serialization is the same as for normal strings */
295 return message_append_field_string(m, h, 'g', s, ret);
296 else {
297 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
298 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
299 if (!p)
300 return -ENOMEM;
301
302 p[0] = (uint8_t) h;
303 p[1] = 1;
304 p[2] = SD_BUS_TYPE_SIGNATURE;
305 p[3] = 0;
306 p[4] = l;
307 memcpy(p + 5, s, l + 1);
308
309 if (ret)
310 *ret = (const char*) p + 5;
311 }
312
313 return 0;
314 }
315
316 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
317 uint8_t *p;
318
319 assert(m);
320
321 /* dbus1 only allows 8bit header field ids */
322 if (h > 0xFF)
323 return -EINVAL;
324
325 if (BUS_MESSAGE_IS_GVARIANT(m)) {
326 /* (field id 64bit + ((value + NUL + signature string 'u') */
327
328 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
329 if (!p)
330 return -ENOMEM;
331
332 *((uint64_t*) p) = h;
333 *((uint32_t*) (p + 8)) = x;
334 p[12] = 0;
335 p[13] = 'u';
336 } else {
337 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
338 p = message_extend_fields(m, 8, 4 + 4, false);
339 if (!p)
340 return -ENOMEM;
341
342 p[0] = (uint8_t) h;
343 p[1] = 1;
344 p[2] = 'u';
345 p[3] = 0;
346
347 ((uint32_t*) p)[1] = x;
348 }
349
350 return 0;
351 }
352
353 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
354 uint8_t *p;
355
356 assert(m);
357
358 /* dbus1 only allows 8bit header field ids */
359 if (h > 0xFF)
360 return -EINVAL;
361
362 if (BUS_MESSAGE_IS_GVARIANT(m)) {
363 /* (field id 64bit + ((value + NUL + signature string 't') */
364
365 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
366 if (!p)
367 return -ENOMEM;
368
369 *((uint64_t*) p) = h;
370 *((uint64_t*) (p + 8)) = x;
371 p[16] = 0;
372 p[17] = 't';
373 } else {
374 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
375 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
376 if (!p)
377 return -ENOMEM;
378
379 p[0] = (uint8_t) h;
380 p[1] = 1;
381 p[2] = 't';
382 p[3] = 0;
383 p[4] = 0;
384 p[5] = 0;
385 p[6] = 0;
386 p[7] = 0;
387
388 ((uint64_t*) p)[1] = x;
389 }
390
391 return 0;
392 }
393
394 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
395 assert(m);
396
397 if (BUS_MESSAGE_IS_GVARIANT(m))
398 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
399 else {
400 /* 64bit cookies are not supported on dbus1 */
401 if (cookie > 0xffffffffUL)
402 return -EOPNOTSUPP;
403
404 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
405 }
406 }
407
408 int bus_message_from_header(
409 sd_bus *bus,
410 void *header,
411 size_t header_accessible,
412 void *footer,
413 size_t footer_accessible,
414 size_t message_size,
415 int *fds,
416 size_t n_fds,
417 const char *label,
418 size_t extra,
419 sd_bus_message **ret) {
420
421 _cleanup_free_ sd_bus_message *m = NULL;
422 struct bus_header *h;
423 size_t a, label_sz;
424
425 assert(bus);
426 assert(header || header_accessible <= 0);
427 assert(footer || footer_accessible <= 0);
428 assert(fds || n_fds <= 0);
429 assert(ret);
430
431 if (header_accessible < sizeof(struct bus_header))
432 return -EBADMSG;
433
434 if (header_accessible > message_size)
435 return -EBADMSG;
436 if (footer_accessible > message_size)
437 return -EBADMSG;
438
439 h = header;
440 if (!IN_SET(h->version, 1, 2))
441 return -EBADMSG;
442
443 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
444 return -EBADMSG;
445
446 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
447 return -EBADMSG;
448
449 /* Note that we are happy with unknown flags in the flags header! */
450
451 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
452
453 if (label) {
454 label_sz = strlen(label);
455 a += label_sz + 1;
456 }
457
458 m = malloc0(a);
459 if (!m)
460 return -ENOMEM;
461
462 m->n_ref = 1;
463 m->sealed = true;
464 m->header = header;
465 m->header_accessible = header_accessible;
466 m->footer = footer;
467 m->footer_accessible = footer_accessible;
468
469 if (BUS_MESSAGE_IS_GVARIANT(m)) {
470 size_t ws;
471
472 if (h->dbus2.cookie == 0)
473 return -EBADMSG;
474
475 /* dbus2 derives the sizes from the message size and
476 the offset table at the end, since it is formatted as
477 gvariant "yyyyuta{tv}v". Since the message itself is a
478 structure with precisely to variable sized entries,
479 there's only one offset in the table, which marks the
480 end of the fields array. */
481
482 ws = bus_gvariant_determine_word_size(message_size, 0);
483 if (footer_accessible < ws)
484 return -EBADMSG;
485
486 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
487 if (ALIGN8(m->fields_size) > message_size - ws)
488 return -EBADMSG;
489 if (m->fields_size < sizeof(struct bus_header))
490 return -EBADMSG;
491
492 m->fields_size -= sizeof(struct bus_header);
493 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
494 } else {
495 if (h->dbus1.serial == 0)
496 return -EBADMSG;
497
498 /* dbus1 has the sizes in the header */
499 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
500 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
501
502 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
503 return -EBADMSG;
504 }
505
506 m->fds = fds;
507 m->n_fds = n_fds;
508
509 if (label) {
510 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
511 memcpy(m->creds.label, label, label_sz + 1);
512
513 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
514 }
515
516 m->bus = sd_bus_ref(bus);
517 *ret = TAKE_PTR(m);
518
519 return 0;
520 }
521
522 int bus_message_from_malloc(
523 sd_bus *bus,
524 void *buffer,
525 size_t length,
526 int *fds,
527 size_t n_fds,
528 const char *label,
529 sd_bus_message **ret) {
530
531 _cleanup_(message_freep) sd_bus_message *m = NULL;
532 size_t sz;
533 int r;
534
535 r = bus_message_from_header(
536 bus,
537 buffer, length, /* in this case the initial bytes and the final bytes are the same */
538 buffer, length,
539 length,
540 fds, n_fds,
541 label,
542 0, &m);
543 if (r < 0)
544 return r;
545
546 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
547 if (sz > 0) {
548 m->n_body_parts = 1;
549 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
550 m->body.size = sz;
551 m->body.sealed = true;
552 m->body.memfd = -1;
553 }
554
555 m->n_iovec = 1;
556 m->iovec = m->iovec_fixed;
557 m->iovec[0].iov_base = buffer;
558 m->iovec[0].iov_len = length;
559
560 r = bus_message_parse_fields(m);
561 if (r < 0)
562 return r;
563
564 /* We take possession of the memory and fds now */
565 m->free_header = true;
566 m->free_fds = true;
567
568 *ret = TAKE_PTR(m);
569 return 0;
570 }
571
572 _public_ int sd_bus_message_new(
573 sd_bus *bus,
574 sd_bus_message **m,
575 uint8_t type) {
576
577 sd_bus_message *t;
578
579 assert_return(bus, -ENOTCONN);
580 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
581 assert_return(m, -EINVAL);
582 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
583
584 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
585 if (!t)
586 return -ENOMEM;
587
588 t->n_ref = 1;
589 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
590 t->header->endian = BUS_NATIVE_ENDIAN;
591 t->header->type = type;
592 t->header->version = bus->message_version;
593 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
594 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
595 t->bus = sd_bus_ref(bus);
596
597 if (bus->allow_interactive_authorization)
598 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
599
600 *m = t;
601 return 0;
602 }
603
604 _public_ int sd_bus_message_new_signal(
605 sd_bus *bus,
606 sd_bus_message **m,
607 const char *path,
608 const char *interface,
609 const char *member) {
610
611 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
612 int r;
613
614 assert_return(bus, -ENOTCONN);
615 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
616 assert_return(object_path_is_valid(path), -EINVAL);
617 assert_return(interface_name_is_valid(interface), -EINVAL);
618 assert_return(member_name_is_valid(member), -EINVAL);
619 assert_return(m, -EINVAL);
620
621 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
622 if (r < 0)
623 return -ENOMEM;
624
625 assert(t);
626
627 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
628
629 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
630 if (r < 0)
631 return r;
632 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
633 if (r < 0)
634 return r;
635 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
636 if (r < 0)
637 return r;
638
639 *m = TAKE_PTR(t);
640 return 0;
641 }
642
643 _public_ int sd_bus_message_new_method_call(
644 sd_bus *bus,
645 sd_bus_message **m,
646 const char *destination,
647 const char *path,
648 const char *interface,
649 const char *member) {
650
651 _cleanup_(message_freep) sd_bus_message *t = NULL;
652 int r;
653
654 assert_return(bus, -ENOTCONN);
655 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
656 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
657 assert_return(object_path_is_valid(path), -EINVAL);
658 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
659 assert_return(member_name_is_valid(member), -EINVAL);
660 assert_return(m, -EINVAL);
661
662 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
663 if (r < 0)
664 return -ENOMEM;
665
666 assert(t);
667
668 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
669 if (r < 0)
670 return r;
671 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
672 if (r < 0)
673 return r;
674
675 if (interface) {
676 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
677 if (r < 0)
678 return r;
679 }
680
681 if (destination) {
682 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
683 if (r < 0)
684 return r;
685 }
686
687 *m = TAKE_PTR(t);
688 return 0;
689 }
690
691 static int message_new_reply(
692 sd_bus_message *call,
693 uint8_t type,
694 sd_bus_message **m) {
695
696 _cleanup_(message_freep) sd_bus_message *t = NULL;
697 uint64_t cookie;
698 int r;
699
700 assert_return(call, -EINVAL);
701 assert_return(call->sealed, -EPERM);
702 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
703 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
704 assert_return(m, -EINVAL);
705
706 cookie = BUS_MESSAGE_COOKIE(call);
707 if (cookie == 0)
708 return -EOPNOTSUPP;
709
710 r = sd_bus_message_new(call->bus, &t, type);
711 if (r < 0)
712 return -ENOMEM;
713
714 assert(t);
715
716 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
717 t->reply_cookie = cookie;
718 r = message_append_reply_cookie(t, t->reply_cookie);
719 if (r < 0)
720 return r;
721
722 if (call->sender) {
723 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
724 if (r < 0)
725 return r;
726 }
727
728 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
729 t->enforced_reply_signature = call->enforced_reply_signature;
730
731 *m = TAKE_PTR(t);
732 return 0;
733 }
734
735 _public_ int sd_bus_message_new_method_return(
736 sd_bus_message *call,
737 sd_bus_message **m) {
738
739 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
740 }
741
742 _public_ int sd_bus_message_new_method_error(
743 sd_bus_message *call,
744 sd_bus_message **m,
745 const sd_bus_error *e) {
746
747 _cleanup_(message_freep) sd_bus_message *t = NULL;
748 int r;
749
750 assert_return(sd_bus_error_is_set(e), -EINVAL);
751 assert_return(m, -EINVAL);
752
753 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
754 if (r < 0)
755 return r;
756
757 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
758 if (r < 0)
759 return r;
760
761 if (e->message) {
762 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
763 if (r < 0)
764 return r;
765 }
766
767 t->error._need_free = -1;
768
769 *m = TAKE_PTR(t);
770 return 0;
771 }
772
773 _public_ int sd_bus_message_new_method_errorf(
774 sd_bus_message *call,
775 sd_bus_message **m,
776 const char *name,
777 const char *format,
778 ...) {
779
780 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
781 va_list ap;
782
783 assert_return(name, -EINVAL);
784 assert_return(m, -EINVAL);
785
786 va_start(ap, format);
787 bus_error_setfv(&error, name, format, ap);
788 va_end(ap);
789
790 return sd_bus_message_new_method_error(call, m, &error);
791 }
792
793 _public_ int sd_bus_message_new_method_errno(
794 sd_bus_message *call,
795 sd_bus_message **m,
796 int error,
797 const sd_bus_error *p) {
798
799 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
800
801 if (sd_bus_error_is_set(p))
802 return sd_bus_message_new_method_error(call, m, p);
803
804 sd_bus_error_set_errno(&berror, error);
805
806 return sd_bus_message_new_method_error(call, m, &berror);
807 }
808
809 _public_ int sd_bus_message_new_method_errnof(
810 sd_bus_message *call,
811 sd_bus_message **m,
812 int error,
813 const char *format,
814 ...) {
815
816 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
817 va_list ap;
818
819 va_start(ap, format);
820 sd_bus_error_set_errnofv(&berror, error, format, ap);
821 va_end(ap);
822
823 return sd_bus_message_new_method_error(call, m, &berror);
824 }
825
826 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
827 assert(bus);
828 assert(m);
829
830 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
831 m->creds.well_known_names_local = true;
832 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
833 }
834
835 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
836 assert(bus);
837 assert(m);
838
839 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
840 m->creds.well_known_names_driver = true;
841 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
842 }
843
844 int bus_message_new_synthetic_error(
845 sd_bus *bus,
846 uint64_t cookie,
847 const sd_bus_error *e,
848 sd_bus_message **m) {
849
850 _cleanup_(message_freep) sd_bus_message *t = NULL;
851 int r;
852
853 assert(bus);
854 assert(sd_bus_error_is_set(e));
855 assert(m);
856
857 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
858 if (r < 0)
859 return -ENOMEM;
860
861 assert(t);
862
863 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
864 t->reply_cookie = cookie;
865
866 r = message_append_reply_cookie(t, t->reply_cookie);
867 if (r < 0)
868 return r;
869
870 if (bus && bus->unique_name) {
871 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
872 if (r < 0)
873 return r;
874 }
875
876 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
877 if (r < 0)
878 return r;
879
880 if (e->message) {
881 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
882 if (r < 0)
883 return r;
884 }
885
886 t->error._need_free = -1;
887
888 bus_message_set_sender_driver(bus, t);
889
890 *m = TAKE_PTR(t);
891 return 0;
892 }
893
894 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_message, sd_bus_message, message_free);
895
896 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
897 assert_return(m, -EINVAL);
898 assert_return(type, -EINVAL);
899
900 *type = m->header->type;
901 return 0;
902 }
903
904 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
905 uint64_t c;
906
907 assert_return(m, -EINVAL);
908 assert_return(cookie, -EINVAL);
909
910 c = BUS_MESSAGE_COOKIE(m);
911 if (c == 0)
912 return -ENODATA;
913
914 *cookie = BUS_MESSAGE_COOKIE(m);
915 return 0;
916 }
917
918 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
919 assert_return(m, -EINVAL);
920 assert_return(cookie, -EINVAL);
921
922 if (m->reply_cookie == 0)
923 return -ENODATA;
924
925 *cookie = m->reply_cookie;
926 return 0;
927 }
928
929 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
930 assert_return(m, -EINVAL);
931
932 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
933 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
934 }
935
936 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
937 assert_return(m, -EINVAL);
938
939 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
940 }
941
942 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
943 assert_return(m, -EINVAL);
944
945 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
946 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
947 }
948
949 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
950 assert_return(m, NULL);
951
952 return m->path;
953 }
954
955 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
956 assert_return(m, NULL);
957
958 return m->interface;
959 }
960
961 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
962 assert_return(m, NULL);
963
964 return m->member;
965 }
966
967 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
968 assert_return(m, NULL);
969
970 return m->destination;
971 }
972
973 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
974 assert_return(m, NULL);
975
976 return m->sender;
977 }
978
979 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
980 assert_return(m, NULL);
981
982 if (!sd_bus_error_is_set(&m->error))
983 return NULL;
984
985 return &m->error;
986 }
987
988 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
989 assert_return(m, -EINVAL);
990 assert_return(usec, -EINVAL);
991
992 if (m->monotonic <= 0)
993 return -ENODATA;
994
995 *usec = m->monotonic;
996 return 0;
997 }
998
999 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1000 assert_return(m, -EINVAL);
1001 assert_return(usec, -EINVAL);
1002
1003 if (m->realtime <= 0)
1004 return -ENODATA;
1005
1006 *usec = m->realtime;
1007 return 0;
1008 }
1009
1010 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1011 assert_return(m, -EINVAL);
1012 assert_return(seqnum, -EINVAL);
1013
1014 if (m->seqnum <= 0)
1015 return -ENODATA;
1016
1017 *seqnum = m->seqnum;
1018 return 0;
1019 }
1020
1021 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1022 assert_return(m, NULL);
1023
1024 if (m->creds.mask == 0)
1025 return NULL;
1026
1027 return &m->creds;
1028 }
1029
1030 _public_ int sd_bus_message_is_signal(
1031 sd_bus_message *m,
1032 const char *interface,
1033 const char *member) {
1034
1035 assert_return(m, -EINVAL);
1036
1037 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1038 return 0;
1039
1040 if (interface && !streq_ptr(m->interface, interface))
1041 return 0;
1042
1043 if (member && !streq_ptr(m->member, member))
1044 return 0;
1045
1046 return 1;
1047 }
1048
1049 _public_ int sd_bus_message_is_method_call(
1050 sd_bus_message *m,
1051 const char *interface,
1052 const char *member) {
1053
1054 assert_return(m, -EINVAL);
1055
1056 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1057 return 0;
1058
1059 if (interface && !streq_ptr(m->interface, interface))
1060 return 0;
1061
1062 if (member && !streq_ptr(m->member, member))
1063 return 0;
1064
1065 return 1;
1066 }
1067
1068 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1069 assert_return(m, -EINVAL);
1070
1071 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1072 return 0;
1073
1074 if (name && !streq_ptr(m->error.name, name))
1075 return 0;
1076
1077 return 1;
1078 }
1079
1080 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1081 assert_return(m, -EINVAL);
1082 assert_return(!m->sealed, -EPERM);
1083 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1084
1085 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1086
1087 return 0;
1088 }
1089
1090 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1091 assert_return(m, -EINVAL);
1092 assert_return(!m->sealed, -EPERM);
1093
1094 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1095
1096 return 0;
1097 }
1098
1099 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1100 assert_return(m, -EINVAL);
1101 assert_return(!m->sealed, -EPERM);
1102
1103 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1104
1105 return 0;
1106 }
1107
1108 struct bus_body_part *message_append_part(sd_bus_message *m) {
1109 struct bus_body_part *part;
1110
1111 assert(m);
1112
1113 if (m->poisoned)
1114 return NULL;
1115
1116 if (m->n_body_parts <= 0) {
1117 part = &m->body;
1118 zero(*part);
1119 } else {
1120 assert(m->body_end);
1121
1122 part = new0(struct bus_body_part, 1);
1123 if (!part) {
1124 m->poisoned = true;
1125 return NULL;
1126 }
1127
1128 m->body_end->next = part;
1129 }
1130
1131 part->memfd = -1;
1132 m->body_end = part;
1133 m->n_body_parts++;
1134
1135 return part;
1136 }
1137
1138 static void part_zero(struct bus_body_part *part, size_t sz) {
1139 assert(part);
1140 assert(sz > 0);
1141 assert(sz < 8);
1142
1143 /* All other fields can be left in their defaults */
1144 assert(!part->data);
1145 assert(part->memfd < 0);
1146
1147 part->size = sz;
1148 part->is_zero = true;
1149 part->sealed = true;
1150 }
1151
1152 static int part_make_space(
1153 struct sd_bus_message *m,
1154 struct bus_body_part *part,
1155 size_t sz,
1156 void **q) {
1157
1158 void *n;
1159
1160 assert(m);
1161 assert(part);
1162 assert(!part->sealed);
1163
1164 if (m->poisoned)
1165 return -ENOMEM;
1166
1167 if (part->allocated == 0 || sz > part->allocated) {
1168 size_t new_allocated;
1169
1170 new_allocated = sz > 0 ? 2 * sz : 64;
1171 n = realloc(part->data, new_allocated);
1172 if (!n) {
1173 m->poisoned = true;
1174 return -ENOMEM;
1175 }
1176
1177 part->data = n;
1178 part->allocated = new_allocated;
1179 part->free_this = true;
1180 }
1181
1182 if (q)
1183 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1184
1185 part->size = sz;
1186 return 0;
1187 }
1188
1189 static int message_add_offset(sd_bus_message *m, size_t offset) {
1190 struct bus_container *c;
1191
1192 assert(m);
1193 assert(BUS_MESSAGE_IS_GVARIANT(m));
1194
1195 /* Add offset to current container, unless this is the first
1196 * item in it, which will have the 0 offset, which we can
1197 * ignore. */
1198 c = message_get_last_container(m);
1199
1200 if (!c->need_offsets)
1201 return 0;
1202
1203 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1204 return -ENOMEM;
1205
1206 c->offsets[c->n_offsets++] = offset;
1207 return 0;
1208 }
1209
1210 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1211 struct bus_container *c;
1212
1213 assert(m);
1214
1215 if (expand <= 0)
1216 return;
1217
1218 /* Update counters */
1219 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1220
1221 if (c->array_size)
1222 *c->array_size += expand;
1223 }
1224 }
1225
1226 static void *message_extend_body(
1227 sd_bus_message *m,
1228 size_t align,
1229 size_t sz,
1230 bool add_offset,
1231 bool force_inline) {
1232
1233 size_t start_body, end_body, padding, added;
1234 void *p;
1235 int r;
1236
1237 assert(m);
1238 assert(align > 0);
1239 assert(!m->sealed);
1240
1241 if (m->poisoned)
1242 return NULL;
1243
1244 start_body = ALIGN_TO((size_t) m->body_size, align);
1245 end_body = start_body + sz;
1246
1247 padding = start_body - m->body_size;
1248 added = padding + sz;
1249
1250 /* Check for 32bit overflows */
1251 if (end_body > (size_t) ((uint32_t) -1) ||
1252 end_body < start_body) {
1253 m->poisoned = true;
1254 return NULL;
1255 }
1256
1257 if (added > 0) {
1258 struct bus_body_part *part = NULL;
1259 bool add_new_part;
1260
1261 add_new_part =
1262 m->n_body_parts <= 0 ||
1263 m->body_end->sealed ||
1264 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1265 (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1266 /* If this must be an inlined extension, let's create a new part if
1267 * the previous part is large enough to be inlined. */
1268
1269 if (add_new_part) {
1270 if (padding > 0) {
1271 part = message_append_part(m);
1272 if (!part)
1273 return NULL;
1274
1275 part_zero(part, padding);
1276 }
1277
1278 part = message_append_part(m);
1279 if (!part)
1280 return NULL;
1281
1282 r = part_make_space(m, part, sz, &p);
1283 if (r < 0)
1284 return NULL;
1285 } else {
1286 struct bus_container *c;
1287 void *op;
1288 size_t os, start_part, end_part;
1289
1290 part = m->body_end;
1291 op = part->data;
1292 os = part->size;
1293
1294 start_part = ALIGN_TO(part->size, align);
1295 end_part = start_part + sz;
1296
1297 r = part_make_space(m, part, end_part, &p);
1298 if (r < 0)
1299 return NULL;
1300
1301 if (padding > 0) {
1302 memzero(p, padding);
1303 p = (uint8_t*) p + padding;
1304 }
1305
1306 /* Readjust pointers */
1307 for (c = m->containers; c < m->containers + m->n_containers; c++)
1308 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1309
1310 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1311 }
1312 } else
1313 /* Return something that is not NULL and is aligned */
1314 p = (uint8_t*) align;
1315
1316 m->body_size = end_body;
1317 message_extend_containers(m, added);
1318
1319 if (add_offset) {
1320 r = message_add_offset(m, end_body);
1321 if (r < 0) {
1322 m->poisoned = true;
1323 return NULL;
1324 }
1325 }
1326
1327 return p;
1328 }
1329
1330 static int message_push_fd(sd_bus_message *m, int fd) {
1331 int *f, copy;
1332
1333 assert(m);
1334
1335 if (fd < 0)
1336 return -EINVAL;
1337
1338 if (!m->allow_fds)
1339 return -EOPNOTSUPP;
1340
1341 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1342 if (copy < 0)
1343 return -errno;
1344
1345 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1346 if (!f) {
1347 m->poisoned = true;
1348 safe_close(copy);
1349 return -ENOMEM;
1350 }
1351
1352 m->fds = f;
1353 m->fds[m->n_fds] = copy;
1354 m->free_fds = true;
1355
1356 return copy;
1357 }
1358
1359 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1360 _cleanup_close_ int fd = -1;
1361 struct bus_container *c;
1362 ssize_t align, sz;
1363 void *a;
1364
1365 assert_return(m, -EINVAL);
1366 assert_return(!m->sealed, -EPERM);
1367 assert_return(bus_type_is_basic(type), -EINVAL);
1368 assert_return(!m->poisoned, -ESTALE);
1369
1370 c = message_get_last_container(m);
1371
1372 if (c->signature && c->signature[c->index]) {
1373 /* Container signature is already set */
1374
1375 if (c->signature[c->index] != type)
1376 return -ENXIO;
1377 } else {
1378 char *e;
1379
1380 /* Maybe we can append to the signature? But only if this is the top-level container */
1381 if (c->enclosing != 0)
1382 return -ENXIO;
1383
1384 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1385 if (!e) {
1386 m->poisoned = true;
1387 return -ENOMEM;
1388 }
1389 }
1390
1391 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1392 uint8_t u8;
1393 uint32_t u32;
1394
1395 switch (type) {
1396
1397 case SD_BUS_TYPE_SIGNATURE:
1398 case SD_BUS_TYPE_STRING:
1399 p = strempty(p);
1400
1401 _fallthrough_;
1402 case SD_BUS_TYPE_OBJECT_PATH:
1403 if (!p)
1404 return -EINVAL;
1405
1406 align = 1;
1407 sz = strlen(p) + 1;
1408 break;
1409
1410 case SD_BUS_TYPE_BOOLEAN:
1411
1412 u8 = p && *(int*) p;
1413 p = &u8;
1414
1415 align = sz = 1;
1416 break;
1417
1418 case SD_BUS_TYPE_UNIX_FD:
1419
1420 if (!p)
1421 return -EINVAL;
1422
1423 fd = message_push_fd(m, *(int*) p);
1424 if (fd < 0)
1425 return fd;
1426
1427 u32 = m->n_fds;
1428 p = &u32;
1429
1430 align = sz = 4;
1431 break;
1432
1433 default:
1434 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1435 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1436 break;
1437 }
1438
1439 assert(align > 0);
1440 assert(sz > 0);
1441
1442 a = message_extend_body(m, align, sz, true, false);
1443 if (!a)
1444 return -ENOMEM;
1445
1446 memcpy(a, p, sz);
1447
1448 if (stored)
1449 *stored = (const uint8_t*) a;
1450
1451 } else {
1452 uint32_t u32;
1453
1454 switch (type) {
1455
1456 case SD_BUS_TYPE_STRING:
1457 /* To make things easy we'll serialize a NULL string
1458 * into the empty string */
1459 p = strempty(p);
1460
1461 _fallthrough_;
1462 case SD_BUS_TYPE_OBJECT_PATH:
1463
1464 if (!p)
1465 return -EINVAL;
1466
1467 align = 4;
1468 sz = 4 + strlen(p) + 1;
1469 break;
1470
1471 case SD_BUS_TYPE_SIGNATURE:
1472
1473 p = strempty(p);
1474
1475 align = 1;
1476 sz = 1 + strlen(p) + 1;
1477 break;
1478
1479 case SD_BUS_TYPE_BOOLEAN:
1480
1481 u32 = p && *(int*) p;
1482 p = &u32;
1483
1484 align = sz = 4;
1485 break;
1486
1487 case SD_BUS_TYPE_UNIX_FD:
1488
1489 if (!p)
1490 return -EINVAL;
1491
1492 fd = message_push_fd(m, *(int*) p);
1493 if (fd < 0)
1494 return fd;
1495
1496 u32 = m->n_fds;
1497 p = &u32;
1498
1499 align = sz = 4;
1500 break;
1501
1502 default:
1503 align = bus_type_get_alignment(type);
1504 sz = bus_type_get_size(type);
1505 break;
1506 }
1507
1508 assert(align > 0);
1509 assert(sz > 0);
1510
1511 a = message_extend_body(m, align, sz, false, false);
1512 if (!a)
1513 return -ENOMEM;
1514
1515 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1516 *(uint32_t*) a = sz - 5;
1517 memcpy((uint8_t*) a + 4, p, sz - 4);
1518
1519 if (stored)
1520 *stored = (const uint8_t*) a + 4;
1521
1522 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1523 *(uint8_t*) a = sz - 2;
1524 memcpy((uint8_t*) a + 1, p, sz - 1);
1525
1526 if (stored)
1527 *stored = (const uint8_t*) a + 1;
1528 } else {
1529 memcpy(a, p, sz);
1530
1531 if (stored)
1532 *stored = a;
1533 }
1534 }
1535
1536 if (type == SD_BUS_TYPE_UNIX_FD)
1537 m->n_fds++;
1538
1539 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1540 c->index++;
1541
1542 fd = -1;
1543 return 0;
1544 }
1545
1546 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1547 return message_append_basic(m, type, p, NULL);
1548 }
1549
1550 _public_ int sd_bus_message_append_string_space(
1551 sd_bus_message *m,
1552 size_t size,
1553 char **s) {
1554
1555 struct bus_container *c;
1556 void *a;
1557
1558 assert_return(m, -EINVAL);
1559 assert_return(s, -EINVAL);
1560 assert_return(!m->sealed, -EPERM);
1561 assert_return(!m->poisoned, -ESTALE);
1562
1563 c = message_get_last_container(m);
1564
1565 if (c->signature && c->signature[c->index]) {
1566 /* Container signature is already set */
1567
1568 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1569 return -ENXIO;
1570 } else {
1571 char *e;
1572
1573 /* Maybe we can append to the signature? But only if this is the top-level container */
1574 if (c->enclosing != 0)
1575 return -ENXIO;
1576
1577 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1578 if (!e) {
1579 m->poisoned = true;
1580 return -ENOMEM;
1581 }
1582 }
1583
1584 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1585 a = message_extend_body(m, 1, size + 1, true, false);
1586 if (!a)
1587 return -ENOMEM;
1588
1589 *s = a;
1590 } else {
1591 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1592 if (!a)
1593 return -ENOMEM;
1594
1595 *(uint32_t*) a = size;
1596 *s = (char*) a + 4;
1597 }
1598
1599 (*s)[size] = 0;
1600
1601 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1602 c->index++;
1603
1604 return 0;
1605 }
1606
1607 _public_ int sd_bus_message_append_string_iovec(
1608 sd_bus_message *m,
1609 const struct iovec *iov,
1610 unsigned n /* should be size_t, but is API now… 😞 */) {
1611
1612 size_t size;
1613 unsigned i;
1614 char *p;
1615 int r;
1616
1617 assert_return(m, -EINVAL);
1618 assert_return(!m->sealed, -EPERM);
1619 assert_return(iov || n == 0, -EINVAL);
1620 assert_return(!m->poisoned, -ESTALE);
1621
1622 size = IOVEC_TOTAL_SIZE(iov, n);
1623
1624 r = sd_bus_message_append_string_space(m, size, &p);
1625 if (r < 0)
1626 return r;
1627
1628 for (i = 0; i < n; i++) {
1629
1630 if (iov[i].iov_base)
1631 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1632 else
1633 memset(p, ' ', iov[i].iov_len);
1634
1635 p += iov[i].iov_len;
1636 }
1637
1638 return 0;
1639 }
1640
1641 static int bus_message_open_array(
1642 sd_bus_message *m,
1643 struct bus_container *c,
1644 const char *contents,
1645 uint32_t **array_size,
1646 size_t *begin,
1647 bool *need_offsets) {
1648
1649 unsigned nindex;
1650 int alignment, r;
1651
1652 assert(m);
1653 assert(c);
1654 assert(contents);
1655 assert(array_size);
1656 assert(begin);
1657 assert(need_offsets);
1658
1659 if (!signature_is_single(contents, true))
1660 return -EINVAL;
1661
1662 if (c->signature && c->signature[c->index]) {
1663
1664 /* Verify the existing signature */
1665
1666 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1667 return -ENXIO;
1668
1669 if (!startswith(c->signature + c->index + 1, contents))
1670 return -ENXIO;
1671
1672 nindex = c->index + 1 + strlen(contents);
1673 } else {
1674 char *e;
1675
1676 if (c->enclosing != 0)
1677 return -ENXIO;
1678
1679 /* Extend the existing signature */
1680
1681 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1682 if (!e) {
1683 m->poisoned = true;
1684 return -ENOMEM;
1685 }
1686
1687 nindex = e - c->signature;
1688 }
1689
1690 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1691 alignment = bus_gvariant_get_alignment(contents);
1692 if (alignment < 0)
1693 return alignment;
1694
1695 /* Add alignment padding and add to offset list */
1696 if (!message_extend_body(m, alignment, 0, false, false))
1697 return -ENOMEM;
1698
1699 r = bus_gvariant_is_fixed_size(contents);
1700 if (r < 0)
1701 return r;
1702
1703 *begin = m->body_size;
1704 *need_offsets = r == 0;
1705 } else {
1706 void *a, *op;
1707 size_t os;
1708 struct bus_body_part *o;
1709
1710 alignment = bus_type_get_alignment(contents[0]);
1711 if (alignment < 0)
1712 return alignment;
1713
1714 a = message_extend_body(m, 4, 4, false, false);
1715 if (!a)
1716 return -ENOMEM;
1717
1718 o = m->body_end;
1719 op = m->body_end->data;
1720 os = m->body_end->size;
1721
1722 /* Add alignment between size and first element */
1723 if (!message_extend_body(m, alignment, 0, false, false))
1724 return -ENOMEM;
1725
1726 /* location of array size might have changed so let's readjust a */
1727 if (o == m->body_end)
1728 a = adjust_pointer(a, op, os, m->body_end->data);
1729
1730 *(uint32_t*) a = 0;
1731 *array_size = a;
1732 }
1733
1734 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1735 c->index = nindex;
1736
1737 return 0;
1738 }
1739
1740 static int bus_message_open_variant(
1741 sd_bus_message *m,
1742 struct bus_container *c,
1743 const char *contents) {
1744
1745 assert(m);
1746 assert(c);
1747 assert(contents);
1748
1749 if (!signature_is_single(contents, false))
1750 return -EINVAL;
1751
1752 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1753 return -EINVAL;
1754
1755 if (c->signature && c->signature[c->index]) {
1756
1757 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1758 return -ENXIO;
1759
1760 } else {
1761 char *e;
1762
1763 if (c->enclosing != 0)
1764 return -ENXIO;
1765
1766 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1767 if (!e) {
1768 m->poisoned = true;
1769 return -ENOMEM;
1770 }
1771 }
1772
1773 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1774 /* Variants are always aligned to 8 */
1775
1776 if (!message_extend_body(m, 8, 0, false, false))
1777 return -ENOMEM;
1778
1779 } else {
1780 size_t l;
1781 void *a;
1782
1783 l = strlen(contents);
1784 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1785 if (!a)
1786 return -ENOMEM;
1787
1788 *(uint8_t*) a = l;
1789 memcpy((uint8_t*) a + 1, contents, l + 1);
1790 }
1791
1792 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1793 c->index++;
1794
1795 return 0;
1796 }
1797
1798 static int bus_message_open_struct(
1799 sd_bus_message *m,
1800 struct bus_container *c,
1801 const char *contents,
1802 size_t *begin,
1803 bool *need_offsets) {
1804
1805 size_t nindex;
1806 int r;
1807
1808 assert(m);
1809 assert(c);
1810 assert(contents);
1811 assert(begin);
1812 assert(need_offsets);
1813
1814 if (!signature_is_valid(contents, false))
1815 return -EINVAL;
1816
1817 if (c->signature && c->signature[c->index]) {
1818 size_t l;
1819
1820 l = strlen(contents);
1821
1822 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1823 !startswith(c->signature + c->index + 1, contents) ||
1824 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1825 return -ENXIO;
1826
1827 nindex = c->index + 1 + l + 1;
1828 } else {
1829 char *e;
1830
1831 if (c->enclosing != 0)
1832 return -ENXIO;
1833
1834 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1835 if (!e) {
1836 m->poisoned = true;
1837 return -ENOMEM;
1838 }
1839
1840 nindex = e - c->signature;
1841 }
1842
1843 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1844 int alignment;
1845
1846 alignment = bus_gvariant_get_alignment(contents);
1847 if (alignment < 0)
1848 return alignment;
1849
1850 if (!message_extend_body(m, alignment, 0, false, false))
1851 return -ENOMEM;
1852
1853 r = bus_gvariant_is_fixed_size(contents);
1854 if (r < 0)
1855 return r;
1856
1857 *begin = m->body_size;
1858 *need_offsets = r == 0;
1859 } else {
1860 /* Align contents to 8 byte boundary */
1861 if (!message_extend_body(m, 8, 0, false, false))
1862 return -ENOMEM;
1863 }
1864
1865 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1866 c->index = nindex;
1867
1868 return 0;
1869 }
1870
1871 static int bus_message_open_dict_entry(
1872 sd_bus_message *m,
1873 struct bus_container *c,
1874 const char *contents,
1875 size_t *begin,
1876 bool *need_offsets) {
1877
1878 int r;
1879
1880 assert(m);
1881 assert(c);
1882 assert(contents);
1883 assert(begin);
1884 assert(need_offsets);
1885
1886 if (!signature_is_pair(contents))
1887 return -EINVAL;
1888
1889 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1890 return -ENXIO;
1891
1892 if (c->signature && c->signature[c->index]) {
1893 size_t l;
1894
1895 l = strlen(contents);
1896
1897 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1898 !startswith(c->signature + c->index + 1, contents) ||
1899 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1900 return -ENXIO;
1901 } else
1902 return -ENXIO;
1903
1904 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1905 int alignment;
1906
1907 alignment = bus_gvariant_get_alignment(contents);
1908 if (alignment < 0)
1909 return alignment;
1910
1911 if (!message_extend_body(m, alignment, 0, false, false))
1912 return -ENOMEM;
1913
1914 r = bus_gvariant_is_fixed_size(contents);
1915 if (r < 0)
1916 return r;
1917
1918 *begin = m->body_size;
1919 *need_offsets = r == 0;
1920 } else {
1921 /* Align contents to 8 byte boundary */
1922 if (!message_extend_body(m, 8, 0, false, false))
1923 return -ENOMEM;
1924 }
1925
1926 return 0;
1927 }
1928
1929 _public_ int sd_bus_message_open_container(
1930 sd_bus_message *m,
1931 char type,
1932 const char *contents) {
1933
1934 struct bus_container *c;
1935 uint32_t *array_size = NULL;
1936 _cleanup_free_ char *signature = NULL;
1937 size_t before, begin = 0;
1938 bool need_offsets = false;
1939 int r;
1940
1941 assert_return(m, -EINVAL);
1942 assert_return(!m->sealed, -EPERM);
1943 assert_return(contents, -EINVAL);
1944 assert_return(!m->poisoned, -ESTALE);
1945
1946 /* Make sure we have space for one more container */
1947 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1948 m->poisoned = true;
1949 return -ENOMEM;
1950 }
1951
1952 c = message_get_last_container(m);
1953
1954 signature = strdup(contents);
1955 if (!signature) {
1956 m->poisoned = true;
1957 return -ENOMEM;
1958 }
1959
1960 /* Save old index in the parent container, in case we have to
1961 * abort this container */
1962 c->saved_index = c->index;
1963 before = m->body_size;
1964
1965 if (type == SD_BUS_TYPE_ARRAY)
1966 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1967 else if (type == SD_BUS_TYPE_VARIANT)
1968 r = bus_message_open_variant(m, c, contents);
1969 else if (type == SD_BUS_TYPE_STRUCT)
1970 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1971 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1972 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1973 else
1974 r = -EINVAL;
1975 if (r < 0)
1976 return r;
1977
1978 /* OK, let's fill it in */
1979 m->containers[m->n_containers++] = (struct bus_container) {
1980 .enclosing = type,
1981 .signature = TAKE_PTR(signature),
1982 .array_size = array_size,
1983 .before = before,
1984 .begin = begin,
1985 .need_offsets = need_offsets,
1986 };
1987
1988 return 0;
1989 }
1990
1991 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1992
1993 assert(m);
1994 assert(c);
1995
1996 if (!BUS_MESSAGE_IS_GVARIANT(m))
1997 return 0;
1998
1999 if (c->need_offsets) {
2000 size_t payload, sz, i;
2001 uint8_t *a;
2002
2003 /* Variable-width arrays */
2004
2005 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2006 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2007
2008 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2009 if (!a)
2010 return -ENOMEM;
2011
2012 for (i = 0; i < c->n_offsets; i++)
2013 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2014 } else {
2015 void *a;
2016
2017 /* Fixed-width or empty arrays */
2018
2019 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2020 if (!a)
2021 return -ENOMEM;
2022 }
2023
2024 return 0;
2025 }
2026
2027 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2028 uint8_t *a;
2029 size_t l;
2030
2031 assert(m);
2032 assert(c);
2033 assert(c->signature);
2034
2035 if (!BUS_MESSAGE_IS_GVARIANT(m))
2036 return 0;
2037
2038 l = strlen(c->signature);
2039
2040 a = message_extend_body(m, 1, 1 + l, true, false);
2041 if (!a)
2042 return -ENOMEM;
2043
2044 a[0] = 0;
2045 memcpy(a+1, c->signature, l);
2046
2047 return 0;
2048 }
2049
2050 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2051 bool fixed_size = true;
2052 size_t n_variable = 0;
2053 unsigned i = 0;
2054 const char *p;
2055 uint8_t *a;
2056 int r;
2057
2058 assert(m);
2059 assert(c);
2060
2061 if (!BUS_MESSAGE_IS_GVARIANT(m))
2062 return 0;
2063
2064 p = strempty(c->signature);
2065 while (*p != 0) {
2066 size_t n;
2067
2068 r = signature_element_length(p, &n);
2069 if (r < 0)
2070 return r;
2071 else {
2072 char t[n+1];
2073
2074 memcpy(t, p, n);
2075 t[n] = 0;
2076
2077 r = bus_gvariant_is_fixed_size(t);
2078 if (r < 0)
2079 return r;
2080 }
2081
2082 assert(!c->need_offsets || i <= c->n_offsets);
2083
2084 /* We need to add an offset for each item that has a
2085 * variable size and that is not the last one in the
2086 * list */
2087 if (r == 0)
2088 fixed_size = false;
2089 if (r == 0 && p[n] != 0)
2090 n_variable++;
2091
2092 i++;
2093 p += n;
2094 }
2095
2096 assert(!c->need_offsets || i == c->n_offsets);
2097 assert(c->need_offsets || n_variable == 0);
2098
2099 if (isempty(c->signature)) {
2100 /* The unary type is encoded as fixed 1 byte padding */
2101 a = message_extend_body(m, 1, 1, add_offset, false);
2102 if (!a)
2103 return -ENOMEM;
2104
2105 *a = 0;
2106 } else if (n_variable <= 0) {
2107 int alignment = 1;
2108
2109 /* Structures with fixed-size members only have to be
2110 * fixed-size themselves. But gvariant requires all fixed-size
2111 * elements to be sized a multiple of their alignment. Hence,
2112 * we must *always* add final padding after the last member so
2113 * the overall size of the structure is properly aligned. */
2114 if (fixed_size)
2115 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2116
2117 assert(alignment > 0);
2118
2119 a = message_extend_body(m, alignment, 0, add_offset, false);
2120 if (!a)
2121 return -ENOMEM;
2122 } else {
2123 size_t sz;
2124 unsigned j;
2125
2126 assert(c->offsets[c->n_offsets-1] == m->body_size);
2127
2128 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2129
2130 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2131 if (!a)
2132 return -ENOMEM;
2133
2134 p = strempty(c->signature);
2135 for (i = 0, j = 0; i < c->n_offsets; i++) {
2136 unsigned k;
2137 size_t n;
2138
2139 r = signature_element_length(p, &n);
2140 if (r < 0)
2141 return r;
2142 else {
2143 char t[n+1];
2144
2145 memcpy(t, p, n);
2146 t[n] = 0;
2147
2148 p += n;
2149
2150 r = bus_gvariant_is_fixed_size(t);
2151 if (r < 0)
2152 return r;
2153 if (r > 0 || p[0] == 0)
2154 continue;
2155 }
2156
2157 k = n_variable - 1 - j;
2158
2159 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2160
2161 j++;
2162 }
2163 }
2164
2165 return 0;
2166 }
2167
2168 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2169 struct bus_container *c;
2170 int r;
2171
2172 assert_return(m, -EINVAL);
2173 assert_return(!m->sealed, -EPERM);
2174 assert_return(m->n_containers > 0, -EINVAL);
2175 assert_return(!m->poisoned, -ESTALE);
2176
2177 c = message_get_last_container(m);
2178
2179 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2180 if (c->signature && c->signature[c->index] != 0)
2181 return -EINVAL;
2182
2183 m->n_containers--;
2184
2185 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2186 r = bus_message_close_array(m, c);
2187 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2188 r = bus_message_close_variant(m, c);
2189 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2190 r = bus_message_close_struct(m, c, true);
2191 else
2192 assert_not_reached("Unknown container type");
2193
2194 free(c->signature);
2195 free(c->offsets);
2196
2197 return r;
2198 }
2199
2200 typedef struct {
2201 const char *types;
2202 unsigned n_struct;
2203 unsigned n_array;
2204 } TypeStack;
2205
2206 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2207 assert(stack);
2208 assert(max > 0);
2209
2210 if (*i >= max)
2211 return -EINVAL;
2212
2213 stack[*i].types = types;
2214 stack[*i].n_struct = n_struct;
2215 stack[*i].n_array = n_array;
2216 (*i)++;
2217
2218 return 0;
2219 }
2220
2221 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2222 assert(stack);
2223 assert(max > 0);
2224 assert(types);
2225 assert(n_struct);
2226 assert(n_array);
2227
2228 if (*i <= 0)
2229 return 0;
2230
2231 (*i)--;
2232 *types = stack[*i].types;
2233 *n_struct = stack[*i].n_struct;
2234 *n_array = stack[*i].n_array;
2235
2236 return 1;
2237 }
2238
2239 _public_ int sd_bus_message_appendv(
2240 sd_bus_message *m,
2241 const char *types,
2242 va_list ap) {
2243
2244 unsigned n_array, n_struct;
2245 TypeStack stack[BUS_CONTAINER_DEPTH];
2246 unsigned stack_ptr = 0;
2247 int r;
2248
2249 assert_return(m, -EINVAL);
2250 assert_return(types, -EINVAL);
2251 assert_return(!m->sealed, -EPERM);
2252 assert_return(!m->poisoned, -ESTALE);
2253
2254 n_array = (unsigned) -1;
2255 n_struct = strlen(types);
2256
2257 for (;;) {
2258 const char *t;
2259
2260 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2261 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2262 if (r < 0)
2263 return r;
2264 if (r == 0)
2265 break;
2266
2267 r = sd_bus_message_close_container(m);
2268 if (r < 0)
2269 return r;
2270
2271 continue;
2272 }
2273
2274 t = types;
2275 if (n_array != (unsigned) -1)
2276 n_array--;
2277 else {
2278 types++;
2279 n_struct--;
2280 }
2281
2282 switch (*t) {
2283
2284 case SD_BUS_TYPE_BYTE: {
2285 uint8_t x;
2286
2287 x = (uint8_t) va_arg(ap, int);
2288 r = sd_bus_message_append_basic(m, *t, &x);
2289 break;
2290 }
2291
2292 case SD_BUS_TYPE_BOOLEAN:
2293 case SD_BUS_TYPE_INT32:
2294 case SD_BUS_TYPE_UINT32:
2295 case SD_BUS_TYPE_UNIX_FD: {
2296 uint32_t x;
2297
2298 /* We assume a boolean is the same as int32_t */
2299 assert_cc(sizeof(int32_t) == sizeof(int));
2300
2301 x = va_arg(ap, uint32_t);
2302 r = sd_bus_message_append_basic(m, *t, &x);
2303 break;
2304 }
2305
2306 case SD_BUS_TYPE_INT16:
2307 case SD_BUS_TYPE_UINT16: {
2308 uint16_t x;
2309
2310 x = (uint16_t) va_arg(ap, int);
2311 r = sd_bus_message_append_basic(m, *t, &x);
2312 break;
2313 }
2314
2315 case SD_BUS_TYPE_INT64:
2316 case SD_BUS_TYPE_UINT64: {
2317 uint64_t x;
2318
2319 x = va_arg(ap, uint64_t);
2320 r = sd_bus_message_append_basic(m, *t, &x);
2321 break;
2322 }
2323
2324 case SD_BUS_TYPE_DOUBLE: {
2325 double x;
2326
2327 x = va_arg(ap, double);
2328 r = sd_bus_message_append_basic(m, *t, &x);
2329 break;
2330 }
2331
2332 case SD_BUS_TYPE_STRING:
2333 case SD_BUS_TYPE_OBJECT_PATH:
2334 case SD_BUS_TYPE_SIGNATURE: {
2335 const char *x;
2336
2337 x = va_arg(ap, const char*);
2338 r = sd_bus_message_append_basic(m, *t, x);
2339 break;
2340 }
2341
2342 case SD_BUS_TYPE_ARRAY: {
2343 size_t k;
2344
2345 r = signature_element_length(t + 1, &k);
2346 if (r < 0)
2347 return r;
2348
2349 {
2350 char s[k + 1];
2351 memcpy(s, t + 1, k);
2352 s[k] = 0;
2353
2354 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2355 if (r < 0)
2356 return r;
2357 }
2358
2359 if (n_array == (unsigned) -1) {
2360 types += k;
2361 n_struct -= k;
2362 }
2363
2364 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2365 if (r < 0)
2366 return r;
2367
2368 types = t + 1;
2369 n_struct = k;
2370 n_array = va_arg(ap, unsigned);
2371
2372 break;
2373 }
2374
2375 case SD_BUS_TYPE_VARIANT: {
2376 const char *s;
2377
2378 s = va_arg(ap, const char*);
2379 if (!s)
2380 return -EINVAL;
2381
2382 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2383 if (r < 0)
2384 return r;
2385
2386 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2387 if (r < 0)
2388 return r;
2389
2390 types = s;
2391 n_struct = strlen(s);
2392 n_array = (unsigned) -1;
2393
2394 break;
2395 }
2396
2397 case SD_BUS_TYPE_STRUCT_BEGIN:
2398 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2399 size_t k;
2400
2401 r = signature_element_length(t, &k);
2402 if (r < 0)
2403 return r;
2404
2405 {
2406 char s[k - 1];
2407
2408 memcpy(s, t + 1, k - 2);
2409 s[k - 2] = 0;
2410
2411 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2412 if (r < 0)
2413 return r;
2414 }
2415
2416 if (n_array == (unsigned) -1) {
2417 types += k - 1;
2418 n_struct -= k - 1;
2419 }
2420
2421 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2422 if (r < 0)
2423 return r;
2424
2425 types = t + 1;
2426 n_struct = k - 2;
2427 n_array = (unsigned) -1;
2428
2429 break;
2430 }
2431
2432 default:
2433 r = -EINVAL;
2434 }
2435
2436 if (r < 0)
2437 return r;
2438 }
2439
2440 return 1;
2441 }
2442
2443 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2444 va_list ap;
2445 int r;
2446
2447 va_start(ap, types);
2448 r = sd_bus_message_appendv(m, types, ap);
2449 va_end(ap);
2450
2451 return r;
2452 }
2453
2454 _public_ int sd_bus_message_append_array_space(
2455 sd_bus_message *m,
2456 char type,
2457 size_t size,
2458 void **ptr) {
2459
2460 ssize_t align, sz;
2461 void *a;
2462 int r;
2463
2464 assert_return(m, -EINVAL);
2465 assert_return(!m->sealed, -EPERM);
2466 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2467 assert_return(ptr || size == 0, -EINVAL);
2468 assert_return(!m->poisoned, -ESTALE);
2469
2470 /* alignment and size of the trivial types (except bool) is
2471 * identical for gvariant and dbus1 marshalling */
2472 align = bus_type_get_alignment(type);
2473 sz = bus_type_get_size(type);
2474
2475 assert_se(align > 0);
2476 assert_se(sz > 0);
2477
2478 if (size % sz != 0)
2479 return -EINVAL;
2480
2481 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2482 if (r < 0)
2483 return r;
2484
2485 a = message_extend_body(m, align, size, false, false);
2486 if (!a)
2487 return -ENOMEM;
2488
2489 r = sd_bus_message_close_container(m);
2490 if (r < 0)
2491 return r;
2492
2493 *ptr = a;
2494 return 0;
2495 }
2496
2497 _public_ int sd_bus_message_append_array(
2498 sd_bus_message *m,
2499 char type,
2500 const void *ptr,
2501 size_t size) {
2502 int r;
2503 void *p;
2504
2505 assert_return(m, -EINVAL);
2506 assert_return(!m->sealed, -EPERM);
2507 assert_return(bus_type_is_trivial(type), -EINVAL);
2508 assert_return(ptr || size == 0, -EINVAL);
2509 assert_return(!m->poisoned, -ESTALE);
2510
2511 r = sd_bus_message_append_array_space(m, type, size, &p);
2512 if (r < 0)
2513 return r;
2514
2515 memcpy_safe(p, ptr, size);
2516
2517 return 0;
2518 }
2519
2520 _public_ int sd_bus_message_append_array_iovec(
2521 sd_bus_message *m,
2522 char type,
2523 const struct iovec *iov,
2524 unsigned n /* should be size_t, but is API now… 😞 */) {
2525
2526 size_t size;
2527 unsigned i;
2528 void *p;
2529 int r;
2530
2531 assert_return(m, -EINVAL);
2532 assert_return(!m->sealed, -EPERM);
2533 assert_return(bus_type_is_trivial(type), -EINVAL);
2534 assert_return(iov || n == 0, -EINVAL);
2535 assert_return(!m->poisoned, -ESTALE);
2536
2537 size = IOVEC_TOTAL_SIZE(iov, n);
2538
2539 r = sd_bus_message_append_array_space(m, type, size, &p);
2540 if (r < 0)
2541 return r;
2542
2543 for (i = 0; i < n; i++) {
2544
2545 if (iov[i].iov_base)
2546 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2547 else
2548 memzero(p, iov[i].iov_len);
2549
2550 p = (uint8_t*) p + iov[i].iov_len;
2551 }
2552
2553 return 0;
2554 }
2555
2556 _public_ int sd_bus_message_append_array_memfd(
2557 sd_bus_message *m,
2558 char type,
2559 int memfd,
2560 uint64_t offset,
2561 uint64_t size) {
2562
2563 _cleanup_close_ int copy_fd = -1;
2564 struct bus_body_part *part;
2565 ssize_t align, sz;
2566 uint64_t real_size;
2567 void *a;
2568 int r;
2569
2570 assert_return(m, -EINVAL);
2571 assert_return(memfd >= 0, -EBADF);
2572 assert_return(bus_type_is_trivial(type), -EINVAL);
2573 assert_return(size > 0, -EINVAL);
2574 assert_return(!m->sealed, -EPERM);
2575 assert_return(!m->poisoned, -ESTALE);
2576
2577 r = memfd_set_sealed(memfd);
2578 if (r < 0)
2579 return r;
2580
2581 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
2582 if (copy_fd < 0)
2583 return copy_fd;
2584
2585 r = memfd_get_size(memfd, &real_size);
2586 if (r < 0)
2587 return r;
2588
2589 if (offset == 0 && size == (uint64_t) -1)
2590 size = real_size;
2591 else if (offset + size > real_size)
2592 return -EMSGSIZE;
2593
2594 align = bus_type_get_alignment(type);
2595 sz = bus_type_get_size(type);
2596
2597 assert_se(align > 0);
2598 assert_se(sz > 0);
2599
2600 if (offset % align != 0)
2601 return -EINVAL;
2602
2603 if (size % sz != 0)
2604 return -EINVAL;
2605
2606 if (size > (uint64_t) (uint32_t) -1)
2607 return -EINVAL;
2608
2609 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2610 if (r < 0)
2611 return r;
2612
2613 a = message_extend_body(m, align, 0, false, false);
2614 if (!a)
2615 return -ENOMEM;
2616
2617 part = message_append_part(m);
2618 if (!part)
2619 return -ENOMEM;
2620
2621 part->memfd = copy_fd;
2622 part->memfd_offset = offset;
2623 part->sealed = true;
2624 part->size = size;
2625 copy_fd = -1;
2626
2627 m->body_size += size;
2628 message_extend_containers(m, size);
2629
2630 return sd_bus_message_close_container(m);
2631 }
2632
2633 _public_ int sd_bus_message_append_string_memfd(
2634 sd_bus_message *m,
2635 int memfd,
2636 uint64_t offset,
2637 uint64_t size) {
2638
2639 _cleanup_close_ int copy_fd = -1;
2640 struct bus_body_part *part;
2641 struct bus_container *c;
2642 uint64_t real_size;
2643 void *a;
2644 int r;
2645
2646 assert_return(m, -EINVAL);
2647 assert_return(memfd >= 0, -EBADF);
2648 assert_return(size > 0, -EINVAL);
2649 assert_return(!m->sealed, -EPERM);
2650 assert_return(!m->poisoned, -ESTALE);
2651
2652 r = memfd_set_sealed(memfd);
2653 if (r < 0)
2654 return r;
2655
2656 copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
2657 if (copy_fd < 0)
2658 return copy_fd;
2659
2660 r = memfd_get_size(memfd, &real_size);
2661 if (r < 0)
2662 return r;
2663
2664 if (offset == 0 && size == (uint64_t) -1)
2665 size = real_size;
2666 else if (offset + size > real_size)
2667 return -EMSGSIZE;
2668
2669 /* We require this to be NUL terminated */
2670 if (size == 0)
2671 return -EINVAL;
2672
2673 if (size > (uint64_t) (uint32_t) -1)
2674 return -EINVAL;
2675
2676 c = message_get_last_container(m);
2677 if (c->signature && c->signature[c->index]) {
2678 /* Container signature is already set */
2679
2680 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2681 return -ENXIO;
2682 } else {
2683 char *e;
2684
2685 /* Maybe we can append to the signature? But only if this is the top-level container */
2686 if (c->enclosing != 0)
2687 return -ENXIO;
2688
2689 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2690 if (!e) {
2691 m->poisoned = true;
2692 return -ENOMEM;
2693 }
2694 }
2695
2696 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2697 a = message_extend_body(m, 4, 4, false, false);
2698 if (!a)
2699 return -ENOMEM;
2700
2701 *(uint32_t*) a = size - 1;
2702 }
2703
2704 part = message_append_part(m);
2705 if (!part)
2706 return -ENOMEM;
2707
2708 part->memfd = copy_fd;
2709 part->memfd_offset = offset;
2710 part->sealed = true;
2711 part->size = size;
2712 copy_fd = -1;
2713
2714 m->body_size += size;
2715 message_extend_containers(m, size);
2716
2717 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2718 r = message_add_offset(m, m->body_size);
2719 if (r < 0) {
2720 m->poisoned = true;
2721 return -ENOMEM;
2722 }
2723 }
2724
2725 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2726 c->index++;
2727
2728 return 0;
2729 }
2730
2731 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2732 char **i;
2733 int r;
2734
2735 assert_return(m, -EINVAL);
2736 assert_return(!m->sealed, -EPERM);
2737 assert_return(!m->poisoned, -ESTALE);
2738
2739 r = sd_bus_message_open_container(m, 'a', "s");
2740 if (r < 0)
2741 return r;
2742
2743 STRV_FOREACH(i, l) {
2744 r = sd_bus_message_append_basic(m, 's', *i);
2745 if (r < 0)
2746 return r;
2747 }
2748
2749 return sd_bus_message_close_container(m);
2750 }
2751
2752 static int bus_message_close_header(sd_bus_message *m) {
2753
2754 assert(m);
2755
2756 /* The actual user data is finished now, we just complete the
2757 variant and struct now (at least on gvariant). Remember
2758 this position, so that during parsing we know where to
2759 put the outer container end. */
2760 m->user_body_size = m->body_size;
2761
2762 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2763 const char *signature;
2764 size_t sz, l;
2765 void *d;
2766
2767 /* Add offset table to end of fields array */
2768 if (m->n_header_offsets >= 1) {
2769 uint8_t *a;
2770 unsigned i;
2771
2772 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2773
2774 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2775 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2776 if (!a)
2777 return -ENOMEM;
2778
2779 for (i = 0; i < m->n_header_offsets; i++)
2780 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2781 }
2782
2783 /* Add gvariant NUL byte plus signature to the end of
2784 * the body, followed by the final offset pointing to
2785 * the end of the fields array */
2786
2787 signature = strempty(m->root_container.signature);
2788 l = strlen(signature);
2789
2790 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2791 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2792 if (!d)
2793 return -ENOMEM;
2794
2795 *(uint8_t*) d = 0;
2796 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2797 memcpy((uint8_t*) d + 2, signature, l);
2798 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2799
2800 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2801
2802 m->footer = d;
2803 m->footer_accessible = 1 + l + 2 + sz;
2804 } else {
2805 m->header->dbus1.fields_size = m->fields_size;
2806 m->header->dbus1.body_size = m->body_size;
2807 }
2808
2809 return 0;
2810 }
2811
2812 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2813 struct bus_body_part *part;
2814 size_t a;
2815 unsigned i;
2816 int r;
2817
2818 assert_return(m, -EINVAL);
2819
2820 if (m->sealed)
2821 return -EPERM;
2822
2823 if (m->n_containers > 0)
2824 return -EBADMSG;
2825
2826 if (m->poisoned)
2827 return -ESTALE;
2828
2829 if (cookie > 0xffffffffULL &&
2830 !BUS_MESSAGE_IS_GVARIANT(m))
2831 return -EOPNOTSUPP;
2832
2833 /* In vtables the return signature of method calls is listed,
2834 * let's check if they match if this is a response */
2835 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2836 m->enforced_reply_signature &&
2837 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2838 return -ENOMSG;
2839
2840 /* If gvariant marshalling is used we need to close the body structure */
2841 r = bus_message_close_struct(m, &m->root_container, false);
2842 if (r < 0)
2843 return r;
2844
2845 /* If there's a non-trivial signature set, then add it in
2846 * here, but only on dbus1 */
2847 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2848 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2849 if (r < 0)
2850 return r;
2851 }
2852
2853 if (m->n_fds > 0) {
2854 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2855 if (r < 0)
2856 return r;
2857 }
2858
2859 r = bus_message_close_header(m);
2860 if (r < 0)
2861 return r;
2862
2863 if (BUS_MESSAGE_IS_GVARIANT(m))
2864 m->header->dbus2.cookie = cookie;
2865 else
2866 m->header->dbus1.serial = (uint32_t) cookie;
2867
2868 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2869
2870 /* Add padding at the end of the fields part, since we know
2871 * the body needs to start at an 8 byte alignment. We made
2872 * sure we allocated enough space for this, so all we need to
2873 * do here is to zero it out. */
2874 a = ALIGN8(m->fields_size) - m->fields_size;
2875 if (a > 0)
2876 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2877
2878 /* If this is something we can send as memfd, then let's seal
2879 the memfd now. Note that we can send memfds as payload only
2880 for directed messages, and not for broadcasts. */
2881 if (m->destination && m->bus->use_memfd) {
2882 MESSAGE_FOREACH_PART(part, i, m)
2883 if (part->memfd >= 0 &&
2884 !part->sealed &&
2885 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2886 part != m->body_end) { /* The last part may never be sent as memfd */
2887 uint64_t sz;
2888
2889 /* Try to seal it if that makes
2890 * sense. First, unmap our own map to
2891 * make sure we don't keep it busy. */
2892 bus_body_part_unmap(part);
2893
2894 /* Then, sync up real memfd size */
2895 sz = part->size;
2896 r = memfd_set_size(part->memfd, sz);
2897 if (r < 0)
2898 return r;
2899
2900 /* Finally, try to seal */
2901 if (memfd_set_sealed(part->memfd) >= 0)
2902 part->sealed = true;
2903 }
2904 }
2905
2906 m->root_container.end = m->user_body_size;
2907 m->root_container.index = 0;
2908 m->root_container.offset_index = 0;
2909 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2910
2911 m->sealed = true;
2912
2913 return 0;
2914 }
2915
2916 int bus_body_part_map(struct bus_body_part *part) {
2917 void *p;
2918 size_t psz, shift;
2919
2920 assert_se(part);
2921
2922 if (part->data)
2923 return 0;
2924
2925 if (part->size <= 0)
2926 return 0;
2927
2928 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2929 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2930 static const uint8_t zeroes[7] = { };
2931 part->data = (void*) zeroes;
2932 return 0;
2933 }
2934
2935 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2936 psz = PAGE_ALIGN(part->size + shift);
2937
2938 if (part->memfd >= 0)
2939 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2940 else if (part->is_zero)
2941 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2942 else
2943 return -EINVAL;
2944
2945 if (p == MAP_FAILED)
2946 return -errno;
2947
2948 part->mapped = psz;
2949 part->mmap_begin = p;
2950 part->data = (uint8_t*) p + shift;
2951 part->munmap_this = true;
2952
2953 return 0;
2954 }
2955
2956 void bus_body_part_unmap(struct bus_body_part *part) {
2957
2958 assert_se(part);
2959
2960 if (part->memfd < 0)
2961 return;
2962
2963 if (!part->mmap_begin)
2964 return;
2965
2966 if (!part->munmap_this)
2967 return;
2968
2969 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2970
2971 part->mmap_begin = NULL;
2972 part->data = NULL;
2973 part->mapped = 0;
2974 part->munmap_this = false;
2975
2976 return;
2977 }
2978
2979 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2980 size_t k, start, end;
2981
2982 assert(rindex);
2983 assert(align > 0);
2984
2985 start = ALIGN_TO((size_t) *rindex, align);
2986 end = start + nbytes;
2987
2988 if (end > sz)
2989 return -EBADMSG;
2990
2991 /* Verify that padding is 0 */
2992 for (k = *rindex; k < start; k++)
2993 if (((const uint8_t*) p)[k] != 0)
2994 return -EBADMSG;
2995
2996 if (r)
2997 *r = (uint8_t*) p + start;
2998
2999 *rindex = end;
3000
3001 return 1;
3002 }
3003
3004 static bool message_end_of_signature(sd_bus_message *m) {
3005 struct bus_container *c;
3006
3007 assert(m);
3008
3009 c = message_get_last_container(m);
3010 return !c->signature || c->signature[c->index] == 0;
3011 }
3012
3013 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3014 struct bus_container *c;
3015
3016 assert(m);
3017
3018 c = message_get_last_container(m);
3019 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3020 return false;
3021
3022 if (BUS_MESSAGE_IS_GVARIANT(m))
3023 return index >= c->end;
3024 else {
3025 assert(c->array_size);
3026 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3027 }
3028 }
3029
3030 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3031 assert_return(m, -EINVAL);
3032 assert_return(m->sealed, -EPERM);
3033
3034 if (complete && m->n_containers > 0)
3035 return false;
3036
3037 if (message_end_of_signature(m))
3038 return true;
3039
3040 if (message_end_of_array(m, m->rindex))
3041 return true;
3042
3043 return false;
3044 }
3045
3046 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3047 struct bus_body_part *part;
3048 size_t begin;
3049 int r;
3050
3051 assert(m);
3052
3053 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3054 part = m->cached_rindex_part;
3055 begin = m->cached_rindex_part_begin;
3056 } else {
3057 part = &m->body;
3058 begin = 0;
3059 }
3060
3061 while (part) {
3062 if (index < begin)
3063 return NULL;
3064
3065 if (index + sz <= begin + part->size) {
3066
3067 r = bus_body_part_map(part);
3068 if (r < 0)
3069 return NULL;
3070
3071 if (p)
3072 *p = (uint8_t*) part->data + index - begin;
3073
3074 m->cached_rindex_part = part;
3075 m->cached_rindex_part_begin = begin;
3076
3077 return part;
3078 }
3079
3080 begin += part->size;
3081 part = part->next;
3082 }
3083
3084 return NULL;
3085 }
3086
3087 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3088 int r;
3089
3090 assert(m);
3091 assert(c);
3092 assert(rindex);
3093
3094 if (!BUS_MESSAGE_IS_GVARIANT(m))
3095 return 0;
3096
3097 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3098 int sz;
3099
3100 sz = bus_gvariant_get_size(c->signature);
3101 if (sz < 0) {
3102 int alignment;
3103
3104 if (c->offset_index+1 >= c->n_offsets)
3105 goto end;
3106
3107 /* Variable-size array */
3108
3109 alignment = bus_gvariant_get_alignment(c->signature);
3110 assert(alignment > 0);
3111
3112 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3113 assert(c->offsets[c->offset_index+1] >= *rindex);
3114 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3115 } else {
3116
3117 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3118 goto end;
3119
3120 /* Fixed-size array */
3121 *rindex = c->begin + (c->offset_index+1) * sz;
3122 c->item_size = sz;
3123 }
3124
3125 c->offset_index++;
3126
3127 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3128
3129 int alignment;
3130 size_t n, j;
3131
3132 if (c->offset_index+1 >= c->n_offsets)
3133 goto end;
3134
3135 r = signature_element_length(c->signature + c->index, &n);
3136 if (r < 0)
3137 return r;
3138
3139 r = signature_element_length(c->signature + c->index + n, &j);
3140 if (r < 0)
3141 return r;
3142 else {
3143 char t[j+1];
3144 memcpy(t, c->signature + c->index + n, j);
3145 t[j] = 0;
3146
3147 alignment = bus_gvariant_get_alignment(t);
3148 }
3149
3150 assert(alignment > 0);
3151
3152 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3153 assert(c->offsets[c->offset_index+1] >= *rindex);
3154 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3155
3156 c->offset_index++;
3157
3158 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3159 goto end;
3160 else
3161 assert_not_reached("Unknown container type");
3162
3163 return 0;
3164
3165 end:
3166 /* Reached the end */
3167 *rindex = c->end;
3168 c->item_size = 0;
3169 return 0;
3170 }
3171
3172 static int message_peek_body(
3173 sd_bus_message *m,
3174 size_t *rindex,
3175 size_t align,
3176 size_t nbytes,
3177 void **ret) {
3178
3179 size_t k, start, end, padding;
3180 struct bus_body_part *part;
3181 uint8_t *q;
3182
3183 assert(m);
3184 assert(rindex);
3185 assert(align > 0);
3186
3187 start = ALIGN_TO((size_t) *rindex, align);
3188 padding = start - *rindex;
3189 end = start + nbytes;
3190
3191 if (end > m->user_body_size)
3192 return -EBADMSG;
3193
3194 part = find_part(m, *rindex, padding, (void**) &q);
3195 if (!part)
3196 return -EBADMSG;
3197
3198 if (q) {
3199 /* Verify padding */
3200 for (k = 0; k < padding; k++)
3201 if (q[k] != 0)
3202 return -EBADMSG;
3203 }
3204
3205 part = find_part(m, start, nbytes, (void**) &q);
3206 if (!part || (nbytes > 0 && !q))
3207 return -EBADMSG;
3208
3209 *rindex = end;
3210
3211 if (ret)
3212 *ret = q;
3213
3214 return 0;
3215 }
3216
3217 static bool validate_nul(const char *s, size_t l) {
3218
3219 /* Check for NUL chars in the string */
3220 if (memchr(s, 0, l))
3221 return false;
3222
3223 /* Check for NUL termination */
3224 if (s[l] != 0)
3225 return false;
3226
3227 return true;
3228 }
3229
3230 static bool validate_string(const char *s, size_t l) {
3231
3232 if (!validate_nul(s, l))
3233 return false;
3234
3235 /* Check if valid UTF8 */
3236 if (!utf8_is_valid(s))
3237 return false;
3238
3239 return true;
3240 }
3241
3242 static bool validate_signature(const char *s, size_t l) {
3243
3244 if (!validate_nul(s, l))
3245 return false;
3246
3247 /* Check if valid signature */
3248 if (!signature_is_valid(s, true))
3249 return false;
3250
3251 return true;
3252 }
3253
3254 static bool validate_object_path(const char *s, size_t l) {
3255
3256 if (!validate_nul(s, l))
3257 return false;
3258
3259 if (!object_path_is_valid(s))
3260 return false;
3261
3262 return true;
3263 }
3264
3265 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3266 struct bus_container *c;
3267 size_t rindex;
3268 void *q;
3269 int r;
3270
3271 assert_return(m, -EINVAL);
3272 assert_return(m->sealed, -EPERM);
3273 assert_return(bus_type_is_basic(type), -EINVAL);
3274
3275 if (message_end_of_signature(m))
3276 return -ENXIO;
3277
3278 if (message_end_of_array(m, m->rindex))
3279 return 0;
3280
3281 c = message_get_last_container(m);
3282 if (c->signature[c->index] != type)
3283 return -ENXIO;
3284
3285 rindex = m->rindex;
3286
3287 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3288
3289 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3290 bool ok;
3291
3292 /* D-Bus spec: The marshalling formats for the string-like types all end
3293 * with a single zero (NUL) byte, but that byte is not considered to be part
3294 * of the text. */
3295 if (c->item_size == 0)
3296 return -EBADMSG;
3297
3298 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3299 if (r < 0)
3300 return r;
3301
3302 if (type == SD_BUS_TYPE_STRING)
3303 ok = validate_string(q, c->item_size-1);
3304 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3305 ok = validate_object_path(q, c->item_size-1);
3306 else
3307 ok = validate_signature(q, c->item_size-1);
3308
3309 if (!ok)
3310 return -EBADMSG;
3311
3312 if (p)
3313 *(const char**) p = q;
3314 } else {
3315 int sz, align;
3316
3317 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3318 assert(sz > 0);
3319 if ((size_t) sz != c->item_size)
3320 return -EBADMSG;
3321
3322 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3323 assert(align > 0);
3324
3325 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3326 if (r < 0)
3327 return r;
3328
3329 switch (type) {
3330
3331 case SD_BUS_TYPE_BYTE:
3332 if (p)
3333 *(uint8_t*) p = *(uint8_t*) q;
3334 break;
3335
3336 case SD_BUS_TYPE_BOOLEAN:
3337 if (p)
3338 *(int*) p = !!*(uint8_t*) q;
3339 break;
3340
3341 case SD_BUS_TYPE_INT16:
3342 case SD_BUS_TYPE_UINT16:
3343 if (p)
3344 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3345 break;
3346
3347 case SD_BUS_TYPE_INT32:
3348 case SD_BUS_TYPE_UINT32:
3349 if (p)
3350 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3351 break;
3352
3353 case SD_BUS_TYPE_INT64:
3354 case SD_BUS_TYPE_UINT64:
3355 case SD_BUS_TYPE_DOUBLE:
3356 if (p)
3357 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3358 break;
3359
3360 case SD_BUS_TYPE_UNIX_FD: {
3361 uint32_t j;
3362
3363 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3364 if (j >= m->n_fds)
3365 return -EBADMSG;
3366
3367 if (p)
3368 *(int*) p = m->fds[j];
3369
3370 break;
3371 }
3372
3373 default:
3374 assert_not_reached("unexpected type");
3375 }
3376 }
3377
3378 r = container_next_item(m, c, &rindex);
3379 if (r < 0)
3380 return r;
3381 } else {
3382
3383 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3384 uint32_t l;
3385 bool ok;
3386
3387 r = message_peek_body(m, &rindex, 4, 4, &q);
3388 if (r < 0)
3389 return r;
3390
3391 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3392 if (l == UINT32_MAX)
3393 /* avoid overflow right below */
3394 return -EBADMSG;
3395
3396 r = message_peek_body(m, &rindex, 1, l+1, &q);
3397 if (r < 0)
3398 return r;
3399
3400 if (type == SD_BUS_TYPE_OBJECT_PATH)
3401 ok = validate_object_path(q, l);
3402 else
3403 ok = validate_string(q, l);
3404 if (!ok)
3405 return -EBADMSG;
3406
3407 if (p)
3408 *(const char**) p = q;
3409
3410 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3411 uint8_t l;
3412
3413 r = message_peek_body(m, &rindex, 1, 1, &q);
3414 if (r < 0)
3415 return r;
3416
3417 l = *(uint8_t*) q;
3418 if (l == UINT8_MAX)
3419 /* avoid overflow right below */
3420 return -EBADMSG;
3421
3422 r = message_peek_body(m, &rindex, 1, l+1, &q);
3423 if (r < 0)
3424 return r;
3425
3426 if (!validate_signature(q, l))
3427 return -EBADMSG;
3428
3429 if (p)
3430 *(const char**) p = q;
3431
3432 } else {
3433 ssize_t sz, align;
3434
3435 align = bus_type_get_alignment(type);
3436 assert(align > 0);
3437
3438 sz = bus_type_get_size(type);
3439 assert(sz > 0);
3440
3441 r = message_peek_body(m, &rindex, align, sz, &q);
3442 if (r < 0)
3443 return r;
3444
3445 switch (type) {
3446
3447 case SD_BUS_TYPE_BYTE:
3448 if (p)
3449 *(uint8_t*) p = *(uint8_t*) q;
3450 break;
3451
3452 case SD_BUS_TYPE_BOOLEAN:
3453 if (p)
3454 *(int*) p = !!*(uint32_t*) q;
3455 break;
3456
3457 case SD_BUS_TYPE_INT16:
3458 case SD_BUS_TYPE_UINT16:
3459 if (p)
3460 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3461 break;
3462
3463 case SD_BUS_TYPE_INT32:
3464 case SD_BUS_TYPE_UINT32:
3465 if (p)
3466 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3467 break;
3468
3469 case SD_BUS_TYPE_INT64:
3470 case SD_BUS_TYPE_UINT64:
3471 case SD_BUS_TYPE_DOUBLE:
3472 if (p)
3473 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3474 break;
3475
3476 case SD_BUS_TYPE_UNIX_FD: {
3477 uint32_t j;
3478
3479 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3480 if (j >= m->n_fds)
3481 return -EBADMSG;
3482
3483 if (p)
3484 *(int*) p = m->fds[j];
3485 break;
3486 }
3487
3488 default:
3489 assert_not_reached("Unknown basic type...");
3490 }
3491 }
3492 }
3493
3494 m->rindex = rindex;
3495
3496 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3497 c->index++;
3498
3499 return 1;
3500 }
3501
3502 static int bus_message_enter_array(
3503 sd_bus_message *m,
3504 struct bus_container *c,
3505 const char *contents,
3506 uint32_t **array_size,
3507 size_t *item_size,
3508 size_t **offsets,
3509 size_t *n_offsets) {
3510
3511 size_t rindex;
3512 void *q;
3513 int r;
3514
3515 assert(m);
3516 assert(c);
3517 assert(contents);
3518 assert(array_size);
3519 assert(item_size);
3520 assert(offsets);
3521 assert(n_offsets);
3522
3523 if (!signature_is_single(contents, true))
3524 return -EINVAL;
3525
3526 if (!c->signature || c->signature[c->index] == 0)
3527 return -ENXIO;
3528
3529 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3530 return -ENXIO;
3531
3532 if (!startswith(c->signature + c->index + 1, contents))
3533 return -ENXIO;
3534
3535 rindex = m->rindex;
3536
3537 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3538 /* dbus1 */
3539 int alignment;
3540
3541 r = message_peek_body(m, &rindex, 4, 4, &q);
3542 if (r < 0)
3543 return r;
3544
3545 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3546 return -EBADMSG;
3547
3548 alignment = bus_type_get_alignment(contents[0]);
3549 if (alignment < 0)
3550 return alignment;
3551
3552 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3553 if (r < 0)
3554 return r;
3555
3556 *array_size = (uint32_t*) q;
3557
3558 } else if (c->item_size <= 0) {
3559
3560 /* gvariant: empty array */
3561 *item_size = 0;
3562 *offsets = NULL;
3563 *n_offsets = 0;
3564
3565 } else if (bus_gvariant_is_fixed_size(contents)) {
3566
3567 /* gvariant: fixed length array */
3568 *item_size = bus_gvariant_get_size(contents);
3569 *offsets = NULL;
3570 *n_offsets = 0;
3571
3572 } else {
3573 size_t where, previous = 0, framing, sz;
3574 int alignment;
3575 unsigned i;
3576
3577 /* gvariant: variable length array */
3578 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3579
3580 where = rindex + c->item_size - sz;
3581 r = message_peek_body(m, &where, 1, sz, &q);
3582 if (r < 0)
3583 return r;
3584
3585 framing = bus_gvariant_read_word_le(q, sz);
3586 if (framing > c->item_size - sz)
3587 return -EBADMSG;
3588 if ((c->item_size - framing) % sz != 0)
3589 return -EBADMSG;
3590
3591 *n_offsets = (c->item_size - framing) / sz;
3592
3593 where = rindex + framing;
3594 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3595 if (r < 0)
3596 return r;
3597
3598 *offsets = new(size_t, *n_offsets);
3599 if (!*offsets)
3600 return -ENOMEM;
3601
3602 alignment = bus_gvariant_get_alignment(c->signature);
3603 assert(alignment > 0);
3604
3605 for (i = 0; i < *n_offsets; i++) {
3606 size_t x, start;
3607
3608 start = ALIGN_TO(previous, alignment);
3609
3610 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3611 if (x > c->item_size - sz)
3612 return -EBADMSG;
3613 if (x < start)
3614 return -EBADMSG;
3615
3616 (*offsets)[i] = rindex + x;
3617 previous = x;
3618 }
3619
3620 *item_size = (*offsets)[0] - rindex;
3621 }
3622
3623 m->rindex = rindex;
3624
3625 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3626 c->index += 1 + strlen(contents);
3627
3628 return 1;
3629 }
3630
3631 static int bus_message_enter_variant(
3632 sd_bus_message *m,
3633 struct bus_container *c,
3634 const char *contents,
3635 size_t *item_size) {
3636
3637 size_t rindex;
3638 uint8_t l;
3639 void *q;
3640 int r;
3641
3642 assert(m);
3643 assert(c);
3644 assert(contents);
3645 assert(item_size);
3646
3647 if (!signature_is_single(contents, false))
3648 return -EINVAL;
3649
3650 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3651 return -EINVAL;
3652
3653 if (!c->signature || c->signature[c->index] == 0)
3654 return -ENXIO;
3655
3656 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3657 return -ENXIO;
3658
3659 rindex = m->rindex;
3660
3661 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3662 size_t k, where;
3663
3664 k = strlen(contents);
3665 if (1+k > c->item_size)
3666 return -EBADMSG;
3667
3668 where = rindex + c->item_size - (1+k);
3669 r = message_peek_body(m, &where, 1, 1+k, &q);
3670 if (r < 0)
3671 return r;
3672
3673 if (*(char*) q != 0)
3674 return -EBADMSG;
3675
3676 if (memcmp((uint8_t*) q+1, contents, k))
3677 return -ENXIO;
3678
3679 *item_size = c->item_size - (1+k);
3680
3681 } else {
3682 r = message_peek_body(m, &rindex, 1, 1, &q);
3683 if (r < 0)
3684 return r;
3685
3686 l = *(uint8_t*) q;
3687 if (l == UINT8_MAX)
3688 /* avoid overflow right below */
3689 return -EBADMSG;
3690
3691 r = message_peek_body(m, &rindex, 1, l+1, &q);
3692 if (r < 0)
3693 return r;
3694
3695 if (!validate_signature(q, l))
3696 return -EBADMSG;
3697
3698 if (!streq(q, contents))
3699 return -ENXIO;
3700 }
3701
3702 m->rindex = rindex;
3703
3704 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3705 c->index++;
3706
3707 return 1;
3708 }
3709
3710 static int build_struct_offsets(
3711 sd_bus_message *m,
3712 const char *signature,
3713 size_t size,
3714 size_t *item_size,
3715 size_t **offsets,
3716 size_t *n_offsets) {
3717
3718 unsigned n_variable = 0, n_total = 0, v;
3719 size_t previous, where;
3720 const char *p;
3721 size_t sz;
3722 void *q;
3723 int r;
3724
3725 assert(m);
3726 assert(item_size);
3727 assert(offsets);
3728 assert(n_offsets);
3729
3730 if (isempty(signature)) {
3731 /* Unary type is encoded as *fixed* 1 byte padding */
3732 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3733 if (r < 0)
3734 return r;
3735
3736 if (*(uint8_t *) q != 0)
3737 return -EBADMSG;
3738
3739 *item_size = 0;
3740 *offsets = NULL;
3741 *n_offsets = 0;
3742 return 0;
3743 }
3744
3745 sz = bus_gvariant_determine_word_size(size, 0);
3746 if (sz <= 0)
3747 return -EBADMSG;
3748
3749 /* First, loop over signature and count variable elements and
3750 * elements in general. We use this to know how large the
3751 * offset array is at the end of the structure. Note that
3752 * GVariant only stores offsets for all variable size elements
3753 * that are not the last item. */
3754
3755 p = signature;
3756 while (*p != 0) {
3757 size_t n;
3758
3759 r = signature_element_length(p, &n);
3760 if (r < 0)
3761 return r;
3762 else {
3763 char t[n+1];
3764
3765 memcpy(t, p, n);
3766 t[n] = 0;
3767
3768 r = bus_gvariant_is_fixed_size(t);
3769 }
3770
3771 if (r < 0)
3772 return r;
3773 if (r == 0 && p[n] != 0) /* except the last item */
3774 n_variable++;
3775 n_total++;
3776
3777 p += n;
3778 }
3779
3780 if (size < n_variable * sz)
3781 return -EBADMSG;
3782
3783 where = m->rindex + size - (n_variable * sz);
3784 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3785 if (r < 0)
3786 return r;
3787
3788 v = n_variable;
3789
3790 *offsets = new(size_t, n_total);
3791 if (!*offsets)
3792 return -ENOMEM;
3793
3794 *n_offsets = 0;
3795
3796 /* Second, loop again and build an offset table */
3797 p = signature;
3798 previous = m->rindex;
3799 while (*p != 0) {
3800 size_t n, offset;
3801 int k;
3802
3803 r = signature_element_length(p, &n);
3804 if (r < 0)
3805 return r;
3806 else {
3807 char t[n+1];
3808
3809 memcpy(t, p, n);
3810 t[n] = 0;
3811
3812 size_t align = bus_gvariant_get_alignment(t);
3813 assert(align > 0);
3814
3815 /* The possible start of this member after including alignment */
3816 size_t start = ALIGN_TO(previous, align);
3817
3818 k = bus_gvariant_get_size(t);
3819 if (k < 0) {
3820 size_t x;
3821
3822 /* Variable size */
3823 if (v > 0) {
3824 v--;
3825
3826 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3827 if (x >= size)
3828 return -EBADMSG;
3829 } else
3830 /* The last item's end is determined
3831 * from the start of the offset array */
3832 x = size - (n_variable * sz);
3833
3834 offset = m->rindex + x;
3835 if (offset < start) {
3836 log_debug("For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3837 t, align, offset, previous, start);
3838 return -EBADMSG;
3839 }
3840 } else
3841 /* Fixed size */
3842 offset = start + k;
3843 }
3844
3845 previous = (*offsets)[(*n_offsets)++] = offset;
3846 p += n;
3847 }
3848
3849 assert(v == 0);
3850 assert(*n_offsets == n_total);
3851
3852 *item_size = (*offsets)[0] - m->rindex;
3853 return 0;
3854 }
3855
3856 static int enter_struct_or_dict_entry(
3857 sd_bus_message *m,
3858 struct bus_container *c,
3859 const char *contents,
3860 size_t *item_size,
3861 size_t **offsets,
3862 size_t *n_offsets) {
3863
3864 int r;
3865
3866 assert(m);
3867 assert(c);
3868 assert(contents);
3869 assert(item_size);
3870 assert(offsets);
3871 assert(n_offsets);
3872
3873 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3874
3875 /* dbus1 */
3876 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3877 if (r < 0)
3878 return r;
3879
3880 } else
3881 /* gvariant with contents */
3882 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3883
3884 return 0;
3885 }
3886
3887 static int bus_message_enter_struct(
3888 sd_bus_message *m,
3889 struct bus_container *c,
3890 const char *contents,
3891 size_t *item_size,
3892 size_t **offsets,
3893 size_t *n_offsets) {
3894
3895 size_t l;
3896 int r;
3897
3898 assert(m);
3899 assert(c);
3900 assert(contents);
3901 assert(item_size);
3902 assert(offsets);
3903 assert(n_offsets);
3904
3905 if (!signature_is_valid(contents, false))
3906 return -EINVAL;
3907
3908 if (!c->signature || c->signature[c->index] == 0)
3909 return -ENXIO;
3910
3911 l = strlen(contents);
3912
3913 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3914 !startswith(c->signature + c->index + 1, contents) ||
3915 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3916 return -ENXIO;
3917
3918 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3919 if (r < 0)
3920 return r;
3921
3922 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3923 c->index += 1 + l + 1;
3924
3925 return 1;
3926 }
3927
3928 static int bus_message_enter_dict_entry(
3929 sd_bus_message *m,
3930 struct bus_container *c,
3931 const char *contents,
3932 size_t *item_size,
3933 size_t **offsets,
3934 size_t *n_offsets) {
3935
3936 size_t l;
3937 int r;
3938
3939 assert(m);
3940 assert(c);
3941 assert(contents);
3942
3943 if (!signature_is_pair(contents))
3944 return -EINVAL;
3945
3946 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3947 return -ENXIO;
3948
3949 if (!c->signature || c->signature[c->index] == 0)
3950 return 0;
3951
3952 l = strlen(contents);
3953
3954 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3955 !startswith(c->signature + c->index + 1, contents) ||
3956 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3957 return -ENXIO;
3958
3959 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3960 if (r < 0)
3961 return r;
3962
3963 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3964 c->index += 1 + l + 1;
3965
3966 return 1;
3967 }
3968
3969 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3970 char type,
3971 const char *contents) {
3972 struct bus_container *c;
3973 uint32_t *array_size = NULL;
3974 _cleanup_free_ char *signature = NULL;
3975 size_t before, end;
3976 _cleanup_free_ size_t *offsets = NULL;
3977 size_t n_offsets = 0, item_size = 0;
3978 int r;
3979
3980 assert_return(m, -EINVAL);
3981 assert_return(m->sealed, -EPERM);
3982 assert_return(type != 0 || !contents, -EINVAL);
3983
3984 if (type == 0 || !contents) {
3985 const char *cc;
3986 char tt;
3987
3988 /* Allow entering into anonymous containers */
3989 r = sd_bus_message_peek_type(m, &tt, &cc);
3990 if (r < 0)
3991 return r;
3992
3993 if (type != 0 && type != tt)
3994 return -ENXIO;
3995
3996 if (contents && !streq(contents, cc))
3997 return -ENXIO;
3998
3999 type = tt;
4000 contents = cc;
4001 }
4002
4003 /*
4004 * We enforce a global limit on container depth, that is much
4005 * higher than the 32 structs and 32 arrays the specification
4006 * mandates. This is simpler to implement for us, and we need
4007 * this only to ensure our container array doesn't grow
4008 * without bounds. We are happy to return any data from a
4009 * message as long as the data itself is valid, even if the
4010 * overall message might be not.
4011 *
4012 * Note that the message signature is validated when
4013 * parsing the headers, and that validation does check the
4014 * 32/32 limit.
4015 *
4016 * Note that the specification defines no limits on the depth
4017 * of stacked variants, but we do.
4018 */
4019 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4020 return -EBADMSG;
4021
4022 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4023 return -ENOMEM;
4024
4025 if (message_end_of_signature(m))
4026 return -ENXIO;
4027
4028 if (message_end_of_array(m, m->rindex))
4029 return 0;
4030
4031 c = message_get_last_container(m);
4032
4033 signature = strdup(contents);
4034 if (!signature)
4035 return -ENOMEM;
4036
4037 c->saved_index = c->index;
4038 before = m->rindex;
4039
4040 if (type == SD_BUS_TYPE_ARRAY)
4041 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4042 else if (type == SD_BUS_TYPE_VARIANT)
4043 r = bus_message_enter_variant(m, c, contents, &item_size);
4044 else if (type == SD_BUS_TYPE_STRUCT)
4045 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4046 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4047 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4048 else
4049 r = -EINVAL;
4050 if (r <= 0)
4051 return r;
4052
4053 /* OK, let's fill it in */
4054 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4055 type == SD_BUS_TYPE_STRUCT &&
4056 isempty(signature))
4057 end = m->rindex + 0;
4058 else
4059 end = m->rindex + c->item_size;
4060
4061 m->containers[m->n_containers++] = (struct bus_container) {
4062 .enclosing = type,
4063 .signature = TAKE_PTR(signature),
4064
4065 .before = before,
4066 .begin = m->rindex,
4067 /* Unary type has fixed size of 1, but virtual size of 0 */
4068 .end = end,
4069 .array_size = array_size,
4070 .item_size = item_size,
4071 .offsets = TAKE_PTR(offsets),
4072 .n_offsets = n_offsets,
4073 };
4074
4075 return 1;
4076 }
4077
4078 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4079 struct bus_container *c;
4080 unsigned saved;
4081 int r;
4082
4083 assert_return(m, -EINVAL);
4084 assert_return(m->sealed, -EPERM);
4085 assert_return(m->n_containers > 0, -ENXIO);
4086
4087 c = message_get_last_container(m);
4088
4089 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4090 if (c->signature && c->signature[c->index] != 0)
4091 return -EBUSY;
4092 }
4093
4094 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4095 if (m->rindex < c->end)
4096 return -EBUSY;
4097
4098 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4099 uint32_t l;
4100
4101 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4102 if (c->begin + l != m->rindex)
4103 return -EBUSY;
4104 }
4105
4106 message_free_last_container(m);
4107
4108 c = message_get_last_container(m);
4109 saved = c->index;
4110 c->index = c->saved_index;
4111 r = container_next_item(m, c, &m->rindex);
4112 c->index = saved;
4113 if (r < 0)
4114 return r;
4115
4116 return 1;
4117 }
4118
4119 static void message_quit_container(sd_bus_message *m) {
4120 struct bus_container *c;
4121
4122 assert(m);
4123 assert(m->sealed);
4124 assert(m->n_containers > 0);
4125
4126 /* Undo seeks */
4127 c = message_get_last_container(m);
4128 assert(m->rindex >= c->before);
4129 m->rindex = c->before;
4130
4131 /* Free container */
4132 message_free_last_container(m);
4133
4134 /* Correct index of new top-level container */
4135 c = message_get_last_container(m);
4136 c->index = c->saved_index;
4137 }
4138
4139 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4140 struct bus_container *c;
4141 int r;
4142
4143 assert_return(m, -EINVAL);
4144 assert_return(m->sealed, -EPERM);
4145
4146 if (message_end_of_signature(m))
4147 goto eof;
4148
4149 if (message_end_of_array(m, m->rindex))
4150 goto eof;
4151
4152 c = message_get_last_container(m);
4153
4154 if (bus_type_is_basic(c->signature[c->index])) {
4155 if (contents)
4156 *contents = NULL;
4157 if (type)
4158 *type = c->signature[c->index];
4159 return 1;
4160 }
4161
4162 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4163
4164 if (contents) {
4165 size_t l;
4166
4167 r = signature_element_length(c->signature+c->index+1, &l);
4168 if (r < 0)
4169 return r;
4170
4171 /* signature_element_length does verification internally */
4172
4173 /* The array element must not be empty */
4174 assert(l >= 1);
4175 if (free_and_strndup(&c->peeked_signature,
4176 c->signature + c->index + 1, l) < 0)
4177 return -ENOMEM;
4178
4179 *contents = c->peeked_signature;
4180 }
4181
4182 if (type)
4183 *type = SD_BUS_TYPE_ARRAY;
4184
4185 return 1;
4186 }
4187
4188 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4189
4190 if (contents) {
4191 size_t l;
4192
4193 r = signature_element_length(c->signature+c->index, &l);
4194 if (r < 0)
4195 return r;
4196
4197 assert(l >= 3);
4198 if (free_and_strndup(&c->peeked_signature,
4199 c->signature + c->index + 1, l - 2) < 0)
4200 return -ENOMEM;
4201
4202 *contents = c->peeked_signature;
4203 }
4204
4205 if (type)
4206 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4207
4208 return 1;
4209 }
4210
4211 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4212 if (contents) {
4213 void *q;
4214
4215 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4216 size_t k;
4217
4218 if (c->item_size < 2)
4219 return -EBADMSG;
4220
4221 /* Look for the NUL delimiter that
4222 separates the payload from the
4223 signature. Since the body might be
4224 in a different part that then the
4225 signature we map byte by byte. */
4226
4227 for (k = 2; k <= c->item_size; k++) {
4228 size_t where;
4229
4230 where = m->rindex + c->item_size - k;
4231 r = message_peek_body(m, &where, 1, k, &q);
4232 if (r < 0)
4233 return r;
4234
4235 if (*(char*) q == 0)
4236 break;
4237 }
4238
4239 if (k > c->item_size)
4240 return -EBADMSG;
4241
4242 if (free_and_strndup(&c->peeked_signature,
4243 (char*) q + 1, k - 1) < 0)
4244 return -ENOMEM;
4245
4246 if (!signature_is_valid(c->peeked_signature, true))
4247 return -EBADMSG;
4248
4249 *contents = c->peeked_signature;
4250 } else {
4251 size_t rindex, l;
4252
4253 rindex = m->rindex;
4254 r = message_peek_body(m, &rindex, 1, 1, &q);
4255 if (r < 0)
4256 return r;
4257
4258 l = *(uint8_t*) q;
4259 if (l == UINT8_MAX)
4260 /* avoid overflow right below */
4261 return -EBADMSG;
4262
4263 r = message_peek_body(m, &rindex, 1, l+1, &q);
4264 if (r < 0)
4265 return r;
4266
4267 if (!validate_signature(q, l))
4268 return -EBADMSG;
4269
4270 *contents = q;
4271 }
4272 }
4273
4274 if (type)
4275 *type = SD_BUS_TYPE_VARIANT;
4276
4277 return 1;
4278 }
4279
4280 return -EINVAL;
4281
4282 eof:
4283 if (type)
4284 *type = 0;
4285 if (contents)
4286 *contents = NULL;
4287 return 0;
4288 }
4289
4290 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4291 struct bus_container *c;
4292
4293 assert_return(m, -EINVAL);
4294 assert_return(m->sealed, -EPERM);
4295
4296 if (complete) {
4297 message_reset_containers(m);
4298 m->rindex = 0;
4299
4300 c = message_get_last_container(m);
4301 } else {
4302 c = message_get_last_container(m);
4303
4304 c->index = 0;
4305 m->rindex = c->begin;
4306 }
4307
4308 c->offset_index = 0;
4309 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4310
4311 return !isempty(c->signature);
4312 }
4313
4314 _public_ int sd_bus_message_readv(
4315 sd_bus_message *m,
4316 const char *types,
4317 va_list ap) {
4318
4319 unsigned n_array, n_struct;
4320 TypeStack stack[BUS_CONTAINER_DEPTH];
4321 unsigned stack_ptr = 0;
4322 unsigned n_loop = 0;
4323 int r;
4324
4325 assert_return(m, -EINVAL);
4326 assert_return(m->sealed, -EPERM);
4327 assert_return(types, -EINVAL);
4328
4329 if (isempty(types))
4330 return 0;
4331
4332 /* Ideally, we'd just call ourselves recursively on every
4333 * complex type. However, the state of a va_list that is
4334 * passed to a function is undefined after that function
4335 * returns. This means we need to decode the va_list linearly
4336 * in a single stackframe. We hence implement our own
4337 * home-grown stack in an array. */
4338
4339 n_array = (unsigned) -1; /* length of current array entries */
4340 n_struct = strlen(types); /* length of current struct contents signature */
4341
4342 for (;;) {
4343 const char *t;
4344
4345 n_loop++;
4346
4347 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4348 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4349 if (r < 0)
4350 return r;
4351 if (r == 0)
4352 break;
4353
4354 r = sd_bus_message_exit_container(m);
4355 if (r < 0)
4356 return r;
4357
4358 continue;
4359 }
4360
4361 t = types;
4362 if (n_array != (unsigned) -1)
4363 n_array--;
4364 else {
4365 types++;
4366 n_struct--;
4367 }
4368
4369 switch (*t) {
4370
4371 case SD_BUS_TYPE_BYTE:
4372 case SD_BUS_TYPE_BOOLEAN:
4373 case SD_BUS_TYPE_INT16:
4374 case SD_BUS_TYPE_UINT16:
4375 case SD_BUS_TYPE_INT32:
4376 case SD_BUS_TYPE_UINT32:
4377 case SD_BUS_TYPE_INT64:
4378 case SD_BUS_TYPE_UINT64:
4379 case SD_BUS_TYPE_DOUBLE:
4380 case SD_BUS_TYPE_STRING:
4381 case SD_BUS_TYPE_OBJECT_PATH:
4382 case SD_BUS_TYPE_SIGNATURE:
4383 case SD_BUS_TYPE_UNIX_FD: {
4384 void *p;
4385
4386 p = va_arg(ap, void*);
4387 r = sd_bus_message_read_basic(m, *t, p);
4388 if (r < 0)
4389 return r;
4390 if (r == 0) {
4391 if (n_loop <= 1)
4392 return 0;
4393
4394 return -ENXIO;
4395 }
4396
4397 break;
4398 }
4399
4400 case SD_BUS_TYPE_ARRAY: {
4401 size_t k;
4402
4403 r = signature_element_length(t + 1, &k);
4404 if (r < 0)
4405 return r;
4406
4407 {
4408 char s[k + 1];
4409 memcpy(s, t + 1, k);
4410 s[k] = 0;
4411
4412 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4413 if (r < 0)
4414 return r;
4415 if (r == 0) {
4416 if (n_loop <= 1)
4417 return 0;
4418
4419 return -ENXIO;
4420 }
4421 }
4422
4423 if (n_array == (unsigned) -1) {
4424 types += k;
4425 n_struct -= k;
4426 }
4427
4428 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4429 if (r < 0)
4430 return r;
4431
4432 types = t + 1;
4433 n_struct = k;
4434 n_array = va_arg(ap, unsigned);
4435
4436 break;
4437 }
4438
4439 case SD_BUS_TYPE_VARIANT: {
4440 const char *s;
4441
4442 s = va_arg(ap, const char *);
4443 if (!s)
4444 return -EINVAL;
4445
4446 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4447 if (r < 0)
4448 return r;
4449 if (r == 0) {
4450 if (n_loop <= 1)
4451 return 0;
4452
4453 return -ENXIO;
4454 }
4455
4456 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4457 if (r < 0)
4458 return r;
4459
4460 types = s;
4461 n_struct = strlen(s);
4462 n_array = (unsigned) -1;
4463
4464 break;
4465 }
4466
4467 case SD_BUS_TYPE_STRUCT_BEGIN:
4468 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4469 size_t k;
4470
4471 r = signature_element_length(t, &k);
4472 if (r < 0)
4473 return r;
4474
4475 {
4476 char s[k - 1];
4477 memcpy(s, t + 1, k - 2);
4478 s[k - 2] = 0;
4479
4480 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4481 if (r < 0)
4482 return r;
4483 if (r == 0) {
4484 if (n_loop <= 1)
4485 return 0;
4486 return -ENXIO;
4487 }
4488 }
4489
4490 if (n_array == (unsigned) -1) {
4491 types += k - 1;
4492 n_struct -= k - 1;
4493 }
4494
4495 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4496 if (r < 0)
4497 return r;
4498
4499 types = t + 1;
4500 n_struct = k - 2;
4501 n_array = (unsigned) -1;
4502
4503 break;
4504 }
4505
4506 default:
4507 return -EINVAL;
4508 }
4509 }
4510
4511 return 1;
4512 }
4513
4514 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4515 va_list ap;
4516 int r;
4517
4518 va_start(ap, types);
4519 r = sd_bus_message_readv(m, types, ap);
4520 va_end(ap);
4521
4522 return r;
4523 }
4524
4525 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4526 int r;
4527
4528 assert_return(m, -EINVAL);
4529 assert_return(m->sealed, -EPERM);
4530
4531 /* If types is NULL, read exactly one element */
4532 if (!types) {
4533 struct bus_container *c;
4534 size_t l;
4535
4536 if (message_end_of_signature(m))
4537 return -ENXIO;
4538
4539 if (message_end_of_array(m, m->rindex))
4540 return 0;
4541
4542 c = message_get_last_container(m);
4543
4544 r = signature_element_length(c->signature + c->index, &l);
4545 if (r < 0)
4546 return r;
4547
4548 types = strndupa(c->signature + c->index, l);
4549 }
4550
4551 switch (*types) {
4552
4553 case 0: /* Nothing to drop */
4554 return 0;
4555
4556 case SD_BUS_TYPE_BYTE:
4557 case SD_BUS_TYPE_BOOLEAN:
4558 case SD_BUS_TYPE_INT16:
4559 case SD_BUS_TYPE_UINT16:
4560 case SD_BUS_TYPE_INT32:
4561 case SD_BUS_TYPE_UINT32:
4562 case SD_BUS_TYPE_INT64:
4563 case SD_BUS_TYPE_UINT64:
4564 case SD_BUS_TYPE_DOUBLE:
4565 case SD_BUS_TYPE_STRING:
4566 case SD_BUS_TYPE_OBJECT_PATH:
4567 case SD_BUS_TYPE_SIGNATURE:
4568 case SD_BUS_TYPE_UNIX_FD:
4569
4570 r = sd_bus_message_read_basic(m, *types, NULL);
4571 if (r <= 0)
4572 return r;
4573
4574 r = sd_bus_message_skip(m, types + 1);
4575 if (r < 0)
4576 return r;
4577
4578 return 1;
4579
4580 case SD_BUS_TYPE_ARRAY: {
4581 size_t k;
4582
4583 r = signature_element_length(types + 1, &k);
4584 if (r < 0)
4585 return r;
4586
4587 {
4588 char s[k+1];
4589 memcpy(s, types+1, k);
4590 s[k] = 0;
4591
4592 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4593 if (r <= 0)
4594 return r;
4595
4596 for (;;) {
4597 r = sd_bus_message_skip(m, s);
4598 if (r < 0)
4599 return r;
4600 if (r == 0)
4601 break;
4602 }
4603
4604 r = sd_bus_message_exit_container(m);
4605 if (r < 0)
4606 return r;
4607 }
4608
4609 r = sd_bus_message_skip(m, types + 1 + k);
4610 if (r < 0)
4611 return r;
4612
4613 return 1;
4614 }
4615
4616 case SD_BUS_TYPE_VARIANT: {
4617 const char *contents;
4618 char x;
4619
4620 r = sd_bus_message_peek_type(m, &x, &contents);
4621 if (r <= 0)
4622 return r;
4623
4624 if (x != SD_BUS_TYPE_VARIANT)
4625 return -ENXIO;
4626
4627 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4628 if (r <= 0)
4629 return r;
4630
4631 r = sd_bus_message_skip(m, contents);
4632 if (r < 0)
4633 return r;
4634 assert(r != 0);
4635
4636 r = sd_bus_message_exit_container(m);
4637 if (r < 0)
4638 return r;
4639
4640 r = sd_bus_message_skip(m, types + 1);
4641 if (r < 0)
4642 return r;
4643
4644 return 1;
4645 }
4646
4647 case SD_BUS_TYPE_STRUCT_BEGIN:
4648 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4649 size_t k;
4650
4651 r = signature_element_length(types, &k);
4652 if (r < 0)
4653 return r;
4654
4655 {
4656 char s[k-1];
4657 memcpy(s, types+1, k-2);
4658 s[k-2] = 0;
4659
4660 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4661 if (r <= 0)
4662 return r;
4663
4664 r = sd_bus_message_skip(m, s);
4665 if (r < 0)
4666 return r;
4667
4668 r = sd_bus_message_exit_container(m);
4669 if (r < 0)
4670 return r;
4671 }
4672
4673 r = sd_bus_message_skip(m, types + k);
4674 if (r < 0)
4675 return r;
4676
4677 return 1;
4678 }
4679
4680 default:
4681 return -EINVAL;
4682 }
4683 }
4684
4685 _public_ int sd_bus_message_read_array(
4686 sd_bus_message *m,
4687 char type,
4688 const void **ptr,
4689 size_t *size) {
4690
4691 struct bus_container *c;
4692 void *p;
4693 size_t sz;
4694 ssize_t align;
4695 int r;
4696
4697 assert_return(m, -EINVAL);
4698 assert_return(m->sealed, -EPERM);
4699 assert_return(bus_type_is_trivial(type), -EINVAL);
4700 assert_return(ptr, -EINVAL);
4701 assert_return(size, -EINVAL);
4702 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4703
4704 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4705 if (r <= 0)
4706 return r;
4707
4708 c = message_get_last_container(m);
4709
4710 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4711 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4712 if (align < 0)
4713 return align;
4714
4715 sz = c->end - c->begin;
4716 } else {
4717 align = bus_type_get_alignment(type);
4718 if (align < 0)
4719 return align;
4720
4721 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4722 }
4723
4724 if (sz == 0)
4725 /* Zero length array, let's return some aligned
4726 * pointer that is not NULL */
4727 p = (uint8_t*) align;
4728 else {
4729 r = message_peek_body(m, &m->rindex, align, sz, &p);
4730 if (r < 0)
4731 goto fail;
4732 }
4733
4734 r = sd_bus_message_exit_container(m);
4735 if (r < 0)
4736 goto fail;
4737
4738 *ptr = (const void*) p;
4739 *size = sz;
4740
4741 return 1;
4742
4743 fail:
4744 message_quit_container(m);
4745 return r;
4746 }
4747
4748 static int message_peek_fields(
4749 sd_bus_message *m,
4750 size_t *rindex,
4751 size_t align,
4752 size_t nbytes,
4753 void **ret) {
4754
4755 assert(m);
4756 assert(rindex);
4757 assert(align > 0);
4758
4759 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4760 }
4761
4762 static int message_peek_field_uint32(
4763 sd_bus_message *m,
4764 size_t *ri,
4765 size_t item_size,
4766 uint32_t *ret) {
4767
4768 int r;
4769 void *q;
4770
4771 assert(m);
4772 assert(ri);
4773
4774 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4775 return -EBADMSG;
4776
4777 /* identical for gvariant and dbus1 */
4778
4779 r = message_peek_fields(m, ri, 4, 4, &q);
4780 if (r < 0)
4781 return r;
4782
4783 if (ret)
4784 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4785
4786 return 0;
4787 }
4788
4789 static int message_peek_field_uint64(
4790 sd_bus_message *m,
4791 size_t *ri,
4792 size_t item_size,
4793 uint64_t *ret) {
4794
4795 int r;
4796 void *q;
4797
4798 assert(m);
4799 assert(ri);
4800
4801 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4802 return -EBADMSG;
4803
4804 /* identical for gvariant and dbus1 */
4805
4806 r = message_peek_fields(m, ri, 8, 8, &q);
4807 if (r < 0)
4808 return r;
4809
4810 if (ret)
4811 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4812
4813 return 0;
4814 }
4815
4816 static int message_peek_field_string(
4817 sd_bus_message *m,
4818 bool (*validate)(const char *p),
4819 size_t *ri,
4820 size_t item_size,
4821 const char **ret) {
4822
4823 uint32_t l;
4824 int r;
4825 void *q;
4826
4827 assert(m);
4828 assert(ri);
4829
4830 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4831
4832 if (item_size <= 0)
4833 return -EBADMSG;
4834
4835 r = message_peek_fields(m, ri, 1, item_size, &q);
4836 if (r < 0)
4837 return r;
4838
4839 l = item_size - 1;
4840 } else {
4841 r = message_peek_field_uint32(m, ri, 4, &l);
4842 if (r < 0)
4843 return r;
4844
4845 if (l == UINT32_MAX)
4846 /* avoid overflow right below */
4847 return -EBADMSG;
4848
4849 r = message_peek_fields(m, ri, 1, l+1, &q);
4850 if (r < 0)
4851 return r;
4852 }
4853
4854 if (validate) {
4855 if (!validate_nul(q, l))
4856 return -EBADMSG;
4857
4858 if (!validate(q))
4859 return -EBADMSG;
4860 } else {
4861 if (!validate_string(q, l))
4862 return -EBADMSG;
4863 }
4864
4865 if (ret)
4866 *ret = q;
4867
4868 return 0;
4869 }
4870
4871 static int message_peek_field_signature(
4872 sd_bus_message *m,
4873 size_t *ri,
4874 size_t item_size,
4875 const char **ret) {
4876
4877 size_t l;
4878 int r;
4879 void *q;
4880
4881 assert(m);
4882 assert(ri);
4883
4884 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4885
4886 if (item_size <= 0)
4887 return -EBADMSG;
4888
4889 r = message_peek_fields(m, ri, 1, item_size, &q);
4890 if (r < 0)
4891 return r;
4892
4893 l = item_size - 1;
4894 } else {
4895 r = message_peek_fields(m, ri, 1, 1, &q);
4896 if (r < 0)
4897 return r;
4898
4899 l = *(uint8_t*) q;
4900 if (l == UINT8_MAX)
4901 /* avoid overflow right below */
4902 return -EBADMSG;
4903
4904 r = message_peek_fields(m, ri, 1, l+1, &q);
4905 if (r < 0)
4906 return r;
4907 }
4908
4909 if (!validate_signature(q, l))
4910 return -EBADMSG;
4911
4912 if (ret)
4913 *ret = q;
4914
4915 return 0;
4916 }
4917
4918 static int message_skip_fields(
4919 sd_bus_message *m,
4920 size_t *ri,
4921 uint32_t array_size,
4922 const char **signature) {
4923
4924 size_t original_index;
4925 int r;
4926
4927 assert(m);
4928 assert(ri);
4929 assert(signature);
4930 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4931
4932 original_index = *ri;
4933
4934 for (;;) {
4935 char t;
4936 size_t l;
4937
4938 if (array_size != (uint32_t) -1 &&
4939 array_size <= *ri - original_index)
4940 return 0;
4941
4942 t = **signature;
4943 if (!t)
4944 return 0;
4945
4946 if (t == SD_BUS_TYPE_STRING) {
4947
4948 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4949 if (r < 0)
4950 return r;
4951
4952 (*signature)++;
4953
4954 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4955
4956 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4957 if (r < 0)
4958 return r;
4959
4960 (*signature)++;
4961
4962 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4963
4964 r = message_peek_field_signature(m, ri, 0, NULL);
4965 if (r < 0)
4966 return r;
4967
4968 (*signature)++;
4969
4970 } else if (bus_type_is_basic(t)) {
4971 ssize_t align, k;
4972
4973 align = bus_type_get_alignment(t);
4974 k = bus_type_get_size(t);
4975 assert(align > 0 && k > 0);
4976
4977 r = message_peek_fields(m, ri, align, k, NULL);
4978 if (r < 0)
4979 return r;
4980
4981 (*signature)++;
4982
4983 } else if (t == SD_BUS_TYPE_ARRAY) {
4984
4985 r = signature_element_length(*signature + 1, &l);
4986 if (r < 0)
4987 return r;
4988
4989 assert(l >= 1);
4990 {
4991 char sig[l + 1], *s = sig;
4992 uint32_t nas;
4993 int alignment;
4994
4995 strncpy(sig, *signature + 1, l);
4996 sig[l] = '\0';
4997
4998 alignment = bus_type_get_alignment(sig[0]);
4999 if (alignment < 0)
5000 return alignment;
5001
5002 r = message_peek_field_uint32(m, ri, 0, &nas);
5003 if (r < 0)
5004 return r;
5005 if (nas > BUS_ARRAY_MAX_SIZE)
5006 return -EBADMSG;
5007
5008 r = message_peek_fields(m, ri, alignment, 0, NULL);
5009 if (r < 0)
5010 return r;
5011
5012 r = message_skip_fields(m, ri, nas, (const char**) &s);
5013 if (r < 0)
5014 return r;
5015 }
5016
5017 (*signature) += 1 + l;
5018
5019 } else if (t == SD_BUS_TYPE_VARIANT) {
5020 const char *s;
5021
5022 r = message_peek_field_signature(m, ri, 0, &s);
5023 if (r < 0)
5024 return r;
5025
5026 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5027 if (r < 0)
5028 return r;
5029
5030 (*signature)++;
5031
5032 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5033
5034 r = signature_element_length(*signature, &l);
5035 if (r < 0)
5036 return r;
5037
5038 assert(l >= 2);
5039 {
5040 char sig[l + 1], *s = sig;
5041 strncpy(sig, *signature + 1, l);
5042 sig[l] = '\0';
5043
5044 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5045 if (r < 0)
5046 return r;
5047 }
5048
5049 *signature += l;
5050 } else
5051 return -EBADMSG;
5052 }
5053 }
5054
5055 int bus_message_parse_fields(sd_bus_message *m) {
5056 size_t ri;
5057 int r;
5058 uint32_t unix_fds = 0;
5059 bool unix_fds_set = false;
5060 void *offsets = NULL;
5061 unsigned n_offsets = 0;
5062 size_t sz = 0;
5063 unsigned i = 0;
5064
5065 assert(m);
5066
5067 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5068 char *p;
5069
5070 /* Read the signature from the end of the body variant first */
5071 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5072 if (m->footer_accessible < 1 + sz)
5073 return -EBADMSG;
5074
5075 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5076 for (;;) {
5077 if (p < (char*) m->footer)
5078 return -EBADMSG;
5079
5080 if (*p == 0) {
5081 char *k;
5082 size_t l;
5083
5084 /* We found the beginning of the signature
5085 * string, yay! We require the body to be a
5086 * structure, so verify it and then strip the
5087 * opening/closing brackets. */
5088
5089 l = (char*) m->footer + m->footer_accessible - p - (1 + sz);
5090 if (l < 2 ||
5091 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5092 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5093 return -EBADMSG;
5094
5095 k = memdup_suffix0(p + 1 + 1, l - 2);
5096 if (!k)
5097 return -ENOMEM;
5098
5099 free_and_replace(m->root_container.signature, k);
5100 break;
5101 }
5102
5103 p--;
5104 }
5105
5106 /* Calculate the actual user body size, by removing
5107 * the trailing variant signature and struct offset
5108 * table */
5109 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5110
5111 /* Pull out the offset table for the fields array */
5112 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5113 if (sz > 0) {
5114 size_t framing;
5115 void *q;
5116
5117 ri = m->fields_size - sz;
5118 r = message_peek_fields(m, &ri, 1, sz, &q);
5119 if (r < 0)
5120 return r;
5121
5122 framing = bus_gvariant_read_word_le(q, sz);
5123 if (framing >= m->fields_size - sz)
5124 return -EBADMSG;
5125 if ((m->fields_size - framing) % sz != 0)
5126 return -EBADMSG;
5127
5128 ri = framing;
5129 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5130 if (r < 0)
5131 return r;
5132
5133 n_offsets = (m->fields_size - framing) / sz;
5134 }
5135 } else
5136 m->user_body_size = m->body_size;
5137
5138 ri = 0;
5139 while (ri < m->fields_size) {
5140 _cleanup_free_ char *sig = NULL;
5141 const char *signature;
5142 uint64_t field_type;
5143 size_t item_size = (size_t) -1;
5144
5145 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5146 uint64_t *u64;
5147
5148 if (i >= n_offsets)
5149 break;
5150
5151 if (i == 0)
5152 ri = 0;
5153 else
5154 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5155
5156 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5157 if (r < 0)
5158 return r;
5159
5160 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5161 } else {
5162 uint8_t *u8;
5163
5164 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5165 if (r < 0)
5166 return r;
5167
5168 field_type = *u8;
5169 }
5170
5171 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5172 size_t where, end;
5173 char *b;
5174 void *q;
5175
5176 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5177
5178 if (end < ri)
5179 return -EBADMSG;
5180
5181 where = ri = ALIGN_TO(ri, 8);
5182 item_size = end - ri;
5183 r = message_peek_fields(m, &where, 1, item_size, &q);
5184 if (r < 0)
5185 return r;
5186
5187 b = memrchr(q, 0, item_size);
5188 if (!b)
5189 return -EBADMSG;
5190
5191 sig = strndup(b+1, item_size - (b+1-(char*) q));
5192 if (!sig)
5193 return -ENOMEM;
5194
5195 signature = sig;
5196 item_size = b - (char*) q;
5197 } else {
5198 r = message_peek_field_signature(m, &ri, 0, &signature);
5199 if (r < 0)
5200 return r;
5201 }
5202
5203 switch (field_type) {
5204
5205 case _BUS_MESSAGE_HEADER_INVALID:
5206 return -EBADMSG;
5207
5208 case BUS_MESSAGE_HEADER_PATH:
5209
5210 if (m->path)
5211 return -EBADMSG;
5212
5213 if (!streq(signature, "o"))
5214 return -EBADMSG;
5215
5216 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5217 break;
5218
5219 case BUS_MESSAGE_HEADER_INTERFACE:
5220
5221 if (m->interface)
5222 return -EBADMSG;
5223
5224 if (!streq(signature, "s"))
5225 return -EBADMSG;
5226
5227 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5228 break;
5229
5230 case BUS_MESSAGE_HEADER_MEMBER:
5231
5232 if (m->member)
5233 return -EBADMSG;
5234
5235 if (!streq(signature, "s"))
5236 return -EBADMSG;
5237
5238 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5239 break;
5240
5241 case BUS_MESSAGE_HEADER_ERROR_NAME:
5242
5243 if (m->error.name)
5244 return -EBADMSG;
5245
5246 if (!streq(signature, "s"))
5247 return -EBADMSG;
5248
5249 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5250 if (r >= 0)
5251 m->error._need_free = -1;
5252
5253 break;
5254
5255 case BUS_MESSAGE_HEADER_DESTINATION:
5256
5257 if (m->destination)
5258 return -EBADMSG;
5259
5260 if (!streq(signature, "s"))
5261 return -EBADMSG;
5262
5263 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5264 break;
5265
5266 case BUS_MESSAGE_HEADER_SENDER:
5267
5268 if (m->sender)
5269 return -EBADMSG;
5270
5271 if (!streq(signature, "s"))
5272 return -EBADMSG;
5273
5274 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5275
5276 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5277 m->creds.unique_name = (char*) m->sender;
5278 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5279 }
5280
5281 break;
5282
5283 case BUS_MESSAGE_HEADER_SIGNATURE: {
5284 const char *s;
5285 char *c;
5286
5287 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5288 return -EBADMSG;
5289
5290 if (m->root_container.signature)
5291 return -EBADMSG;
5292
5293 if (!streq(signature, "g"))
5294 return -EBADMSG;
5295
5296 r = message_peek_field_signature(m, &ri, item_size, &s);
5297 if (r < 0)
5298 return r;
5299
5300 c = strdup(s);
5301 if (!c)
5302 return -ENOMEM;
5303
5304 free_and_replace(m->root_container.signature, c);
5305 break;
5306 }
5307
5308 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5309
5310 if (m->reply_cookie != 0)
5311 return -EBADMSG;
5312
5313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5314 /* 64bit on dbus2 */
5315
5316 if (!streq(signature, "t"))
5317 return -EBADMSG;
5318
5319 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5320 if (r < 0)
5321 return r;
5322 } else {
5323 /* 32bit on dbus1 */
5324 uint32_t serial;
5325
5326 if (!streq(signature, "u"))
5327 return -EBADMSG;
5328
5329 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5330 if (r < 0)
5331 return r;
5332
5333 m->reply_cookie = serial;
5334 }
5335
5336 if (m->reply_cookie == 0)
5337 return -EBADMSG;
5338
5339 break;
5340
5341 case BUS_MESSAGE_HEADER_UNIX_FDS:
5342 if (unix_fds_set)
5343 return -EBADMSG;
5344
5345 if (!streq(signature, "u"))
5346 return -EBADMSG;
5347
5348 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5349 if (r < 0)
5350 return -EBADMSG;
5351
5352 unix_fds_set = true;
5353 break;
5354
5355 default:
5356 if (!BUS_MESSAGE_IS_GVARIANT(m))
5357 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5358 }
5359
5360 if (r < 0)
5361 return r;
5362
5363 i++;
5364 }
5365
5366 if (m->n_fds != unix_fds)
5367 return -EBADMSG;
5368
5369 switch (m->header->type) {
5370
5371 case SD_BUS_MESSAGE_SIGNAL:
5372 if (!m->path || !m->interface || !m->member)
5373 return -EBADMSG;
5374
5375 if (m->reply_cookie != 0)
5376 return -EBADMSG;
5377
5378 break;
5379
5380 case SD_BUS_MESSAGE_METHOD_CALL:
5381
5382 if (!m->path || !m->member)
5383 return -EBADMSG;
5384
5385 if (m->reply_cookie != 0)
5386 return -EBADMSG;
5387
5388 break;
5389
5390 case SD_BUS_MESSAGE_METHOD_RETURN:
5391
5392 if (m->reply_cookie == 0)
5393 return -EBADMSG;
5394 break;
5395
5396 case SD_BUS_MESSAGE_METHOD_ERROR:
5397
5398 if (m->reply_cookie == 0 || !m->error.name)
5399 return -EBADMSG;
5400 break;
5401 }
5402
5403 /* Refuse non-local messages that claim they are local */
5404 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5405 return -EBADMSG;
5406 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5407 return -EBADMSG;
5408 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5409 return -EBADMSG;
5410
5411 m->root_container.end = m->user_body_size;
5412
5413 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5414 r = build_struct_offsets(
5415 m,
5416 m->root_container.signature,
5417 m->user_body_size,
5418 &m->root_container.item_size,
5419 &m->root_container.offsets,
5420 &m->root_container.n_offsets);
5421 if (r == -EINVAL)
5422 return -EBADMSG;
5423 if (r < 0)
5424 return r;
5425 }
5426
5427 /* Try to read the error message, but if we can't it's a non-issue */
5428 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5429 (void) sd_bus_message_read(m, "s", &m->error.message);
5430
5431 return 0;
5432 }
5433
5434 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5435 assert_return(m, -EINVAL);
5436 assert_return(destination, -EINVAL);
5437 assert_return(service_name_is_valid(destination), -EINVAL);
5438 assert_return(!m->sealed, -EPERM);
5439 assert_return(!m->destination, -EEXIST);
5440
5441 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5442 }
5443
5444 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5445 assert_return(m, -EINVAL);
5446 assert_return(sender, -EINVAL);
5447 assert_return(service_name_is_valid(sender), -EINVAL);
5448 assert_return(!m->sealed, -EPERM);
5449 assert_return(!m->sender, -EEXIST);
5450
5451 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5452 }
5453
5454 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5455 size_t total;
5456 void *p, *e;
5457 size_t i;
5458 struct bus_body_part *part;
5459
5460 assert(m);
5461 assert(buffer);
5462 assert(sz);
5463
5464 total = BUS_MESSAGE_SIZE(m);
5465
5466 p = malloc(total);
5467 if (!p)
5468 return -ENOMEM;
5469
5470 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5471 MESSAGE_FOREACH_PART(part, i, m)
5472 e = mempcpy(e, part->data, part->size);
5473
5474 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5475
5476 *buffer = p;
5477 *sz = total;
5478
5479 return 0;
5480 }
5481
5482 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5483 const char *s;
5484 int r;
5485
5486 assert(m);
5487 assert(l);
5488
5489 r = sd_bus_message_enter_container(m, 'a', "s");
5490 if (r <= 0)
5491 return r;
5492
5493 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5494 r = strv_extend(l, s);
5495 if (r < 0)
5496 return r;
5497 }
5498 if (r < 0)
5499 return r;
5500
5501 r = sd_bus_message_exit_container(m);
5502 if (r < 0)
5503 return r;
5504
5505 return 1;
5506 }
5507
5508 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5509 _cleanup_strv_free_ char **strv = NULL;
5510 int r;
5511
5512 assert_return(m, -EINVAL);
5513 assert_return(m->sealed, -EPERM);
5514 assert_return(l, -EINVAL);
5515
5516 r = bus_message_read_strv_extend(m, &strv);
5517 if (r <= 0)
5518 return r;
5519
5520 *l = TAKE_PTR(strv);
5521 return 1;
5522 }
5523
5524 static int bus_message_get_arg_skip(
5525 sd_bus_message *m,
5526 unsigned i,
5527 char *_type,
5528 const char **_contents) {
5529
5530 unsigned j;
5531 int r;
5532
5533 r = sd_bus_message_rewind(m, true);
5534 if (r < 0)
5535 return r;
5536
5537 for (j = 0;; j++) {
5538 const char *contents;
5539 char type;
5540
5541 r = sd_bus_message_peek_type(m, &type, &contents);
5542 if (r < 0)
5543 return r;
5544 if (r == 0)
5545 return -ENXIO;
5546
5547 /* Don't match against arguments after the first one we don't understand */
5548 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5549 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5550 return -ENXIO;
5551
5552 if (j >= i) {
5553 if (_contents)
5554 *_contents = contents;
5555 if (_type)
5556 *_type = type;
5557 return 0;
5558 }
5559
5560 r = sd_bus_message_skip(m, NULL);
5561 if (r < 0)
5562 return r;
5563 }
5564
5565 }
5566
5567 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5568 char type;
5569 int r;
5570
5571 assert(m);
5572 assert(str);
5573
5574 r = bus_message_get_arg_skip(m, i, &type, NULL);
5575 if (r < 0)
5576 return r;
5577
5578 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5579 return -ENXIO;
5580
5581 return sd_bus_message_read_basic(m, type, str);
5582 }
5583
5584 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5585 const char *contents;
5586 char type;
5587 int r;
5588
5589 assert(m);
5590 assert(strv);
5591
5592 r = bus_message_get_arg_skip(m, i, &type, &contents);
5593 if (r < 0)
5594 return r;
5595
5596 if (type != SD_BUS_TYPE_ARRAY)
5597 return -ENXIO;
5598 if (!STR_IN_SET(contents, "s", "o", "g"))
5599 return -ENXIO;
5600
5601 return sd_bus_message_read_strv(m, strv);
5602 }
5603
5604 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5605 assert_return(m, EINVAL);
5606
5607 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5608 return 0;
5609
5610 return sd_bus_error_get_errno(&m->error);
5611 }
5612
5613 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5614 struct bus_container *c;
5615
5616 assert_return(m, NULL);
5617
5618 c = complete ? &m->root_container : message_get_last_container(m);
5619 return strempty(c->signature);
5620 }
5621
5622 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5623 assert_return(m, -EINVAL);
5624
5625 return isempty(m->root_container.signature);
5626 }
5627
5628 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5629 assert_return(m, -EINVAL);
5630
5631 return streq(strempty(m->root_container.signature), strempty(signature));
5632 }
5633
5634 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5635 bool done_something = false;
5636 int r;
5637
5638 assert_return(m, -EINVAL);
5639 assert_return(source, -EINVAL);
5640 assert_return(!m->sealed, -EPERM);
5641 assert_return(source->sealed, -EPERM);
5642
5643 do {
5644 const char *contents;
5645 char type;
5646 union {
5647 uint8_t u8;
5648 uint16_t u16;
5649 int16_t s16;
5650 uint32_t u32;
5651 int32_t s32;
5652 uint64_t u64;
5653 int64_t s64;
5654 double d64;
5655 const char *string;
5656 int i;
5657 } basic;
5658
5659 r = sd_bus_message_peek_type(source, &type, &contents);
5660 if (r < 0)
5661 return r;
5662 if (r == 0)
5663 break;
5664
5665 done_something = true;
5666
5667 if (bus_type_is_container(type) > 0) {
5668
5669 r = sd_bus_message_enter_container(source, type, contents);
5670 if (r < 0)
5671 return r;
5672
5673 r = sd_bus_message_open_container(m, type, contents);
5674 if (r < 0)
5675 return r;
5676
5677 r = sd_bus_message_copy(m, source, true);
5678 if (r < 0)
5679 return r;
5680
5681 r = sd_bus_message_close_container(m);
5682 if (r < 0)
5683 return r;
5684
5685 r = sd_bus_message_exit_container(source);
5686 if (r < 0)
5687 return r;
5688
5689 continue;
5690 }
5691
5692 r = sd_bus_message_read_basic(source, type, &basic);
5693 if (r < 0)
5694 return r;
5695
5696 assert(r > 0);
5697
5698 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5699 r = sd_bus_message_append_basic(m, type, basic.string);
5700 else
5701 r = sd_bus_message_append_basic(m, type, &basic);
5702
5703 if (r < 0)
5704 return r;
5705
5706 } while (all);
5707
5708 return done_something;
5709 }
5710
5711 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5712 const char *c;
5713 char t;
5714 int r;
5715
5716 assert_return(m, -EINVAL);
5717 assert_return(m->sealed, -EPERM);
5718 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5719 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5720 assert_return(type || contents, -EINVAL);
5721 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5722
5723 r = sd_bus_message_peek_type(m, &t, &c);
5724 if (r <= 0)
5725 return r;
5726
5727 if (type != 0 && type != t)
5728 return 0;
5729
5730 if (contents && !streq_ptr(contents, c))
5731 return 0;
5732
5733 return 1;
5734 }
5735
5736 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5737 assert_return(m, NULL);
5738
5739 return m->bus;
5740 }
5741
5742 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5743 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5744 usec_t timeout;
5745 int r;
5746
5747 assert(bus);
5748 assert(m);
5749 assert(*m);
5750
5751 switch ((*m)->header->type) {
5752
5753 case SD_BUS_MESSAGE_SIGNAL:
5754 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5755 if (r < 0)
5756 return r;
5757
5758 break;
5759
5760 case SD_BUS_MESSAGE_METHOD_CALL:
5761 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5762 if (r < 0)
5763 return r;
5764
5765 break;
5766
5767 case SD_BUS_MESSAGE_METHOD_RETURN:
5768 case SD_BUS_MESSAGE_METHOD_ERROR:
5769
5770 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5771 if (r < 0)
5772 return -ENOMEM;
5773
5774 assert(n);
5775
5776 n->reply_cookie = (*m)->reply_cookie;
5777
5778 r = message_append_reply_cookie(n, n->reply_cookie);
5779 if (r < 0)
5780 return r;
5781
5782 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5783 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5784 if (r < 0)
5785 return r;
5786
5787 n->error._need_free = -1;
5788 }
5789
5790 break;
5791
5792 default:
5793 return -EINVAL;
5794 }
5795
5796 if ((*m)->destination && !n->destination) {
5797 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5798 if (r < 0)
5799 return r;
5800 }
5801
5802 if ((*m)->sender && !n->sender) {
5803 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5804 if (r < 0)
5805 return r;
5806 }
5807
5808 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5809
5810 r = sd_bus_message_copy(n, *m, true);
5811 if (r < 0)
5812 return r;
5813
5814 timeout = (*m)->timeout;
5815 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) {
5816 r = sd_bus_get_method_call_timeout(bus, &timeout);
5817 if (r < 0)
5818 return r;
5819 }
5820
5821 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5822 if (r < 0)
5823 return r;
5824
5825 sd_bus_message_unref(*m);
5826 *m = TAKE_PTR(n);
5827
5828 return 0;
5829 }
5830
5831 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5832 assert(m);
5833 assert(sender);
5834
5835 assert_return(!m->sealed, -EPERM);
5836 assert_return(!m->sender, -EPERM);
5837
5838 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5839 }
5840
5841 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5842 assert_return(m, -EINVAL);
5843 assert_return(priority, -EINVAL);
5844
5845 *priority = m->priority;
5846 return 0;
5847 }
5848
5849 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5850 assert_return(m, -EINVAL);
5851 assert_return(!m->sealed, -EPERM);
5852
5853 m->priority = priority;
5854 return 0;
5855 }