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